CovarianceTests.java
/*******************************************************************************
* Copyright (c) 2004 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/org/documents/epl-2.0/EPL-2.0.txt
*
* Contributors:
* Andy Clement - initial implementation
*******************************************************************************/
package org.aspectj.systemtest.ajc150;
import org.aspectj.testing.XMLBasedAjcTestCase;
import junit.framework.Test;
/*
class Car {}
class FastCar extends Car {}
class Super {
Car getCar() {
return new Car();
}
}
class Sub extends Super {
FastCar getCar() {
return new FastCar();
}
}
public class CovBaseProgram01 {
public static void main(String[] argv) {
new CovBaseProgram01().run();
}
public void run() {
Super instance_super = new Super();
Sub instance_sub = new Sub();
Car c1 = instance_super.getCar(); // Line 26
Car c2 = instance_sub.getCar(); // Line 27
}
}
// Line26: callJPs: call(Car Super.getCar())
// Line27: callJPs: call(FastCar Sub.getCar()) call(Car Super.getCar())
*/
/**
* Covariance is simply where a type overrides some inherited implementation and narrows the return type.
*/
public class CovarianceTests extends XMLBasedAjcTestCase {
public static Test suite() {
return XMLBasedAjcTestCase.loadSuite(CovarianceTests.class);
}
protected java.net.URL getSpecFile() {
return getClassResource("ajc150.xml");
}
private boolean verbose = false;
/**
* call(* getCar()) should match both
*/
public void testCOV001() {
runTest("covariance 1");
}
/**
* call(* Super.getCar()) should match both
*
* This test required a change to the compiler. When we are looking at signatures and comparing them we walk up
* the hierarchy looking for supertypes that declare the same method. The problem is that in the comparison for
* whether to methods are compatible we were including the return type - this meant 'Car getCar()' on Super was
* different to 'FastCar getCar()' on Sub - it thought they were entirely different methods. In fact the return
* type is irrelevant here, we just want to make sure the names and the parameter types are the same - so I
* added a parameterSignature to the Member class that looks like '()' where the full signature looks like
* '()LFastCar;' (which includes the return type). If the full signature comparison fails then it looks at the
* parameter signature - I did it that way to try and preserve some performance. I haven't changed the
* definition of 'signature' for a member as trimming the return type off it seems rather serious !
*
* What might break:
* - 'matches' can now return true for things that have different return types - I guess whether this is a problem
* depends on what the caller of matches is expecting, their code will have been written before covariance was
* a possibility. All the tests pass so I'll leave it like this for now.
*/
public void testCOV002() {
runTest("covariance 2");
}
/**
* call(Car getCar()) should match both
*
* Had to implement proper covariance support here...
*/
public void testCOV003() {
runTest("covariance 3");
}
/**
* *** Different base program, where Sub does not extend Super.
* call(Car Super.getCar()) should only match first call to getCar()
*/
public void testCOV004() {
runTest("covariance 4");
}
/**
* *** Original base program
* call(Car Super.getCar()) should match both
*/
public void testCOV005() {
runTest("covariance 5");
}
/**
* call(Car Sub.getCar()) should not match anything
*/
public void testCOV006() {
runTest("covariance 6");
}
/**
* call(Car+ Sub.getCar()) should match 2nd call with xlint for the 1st call
*/
public void testCOV007() {
runTest("covariance 7");
}
/**
* *** aspect now contains two pointcuts and two pieces of advice
* call(FastCar getCar()) matches on 2nd call
* call(FastCar Sub.getCar()) matches on 2nd call
*/
public void testCOV008() {
runTest("covariance 8");
}
/**
* call(FastCar Super.getCar()) matches nothing
*/
public void testCOV009() {
runTest("covariance 9");
}
/**
* call(Car+ getCar()) matches both
*/
public void testCOV010() {
runTest("covariance 10");
}
public void testAJDKExamples() {
runTest("ajdk: covariance");
}
}