/** * Copyright (c) 2009-2011, The HATS Consortium. All rights reserved. * This file is licensed under the terms of the Modified BSD License. */ package abs.frontend.typesystem; import org.junit.Test; import abs.frontend.FrontendTest; import abs.frontend.analyser.SemanticCondition; import static abs.ABSTest.Config.*; public class ModuleSystemTests extends FrontendTest { @Test public void simpleModule() { assertTypeOK("module A;"); } @Test public void simpleModule2() { assertTypeOK("module A; module B;"); } @Test public void simpleModule3() { assertTypeOK("module A; data X; module B;"); } @Test public void qualifiedImport() { assertTypeOK("module A; export Foo, Bar; data Foo = Bar; module B; import A.Foo; import A.Bar; { A.Foo f = A.Bar; } "); } @Test public void starImport() { assertTypeOK("module A; export X; data X; module B; import * from A; type Y = X;"); } @Test public void exportedImport() { assertTypeOK("module A; export X; data X; module B; import A.X; type Y = A.X;"); } @Test public void starExportedImport() { assertTypeOK("module A; export X; data X; module B; export * from A; import A.X; module C; import * from B; type Y = B.X;"); } @Test public void fromExportedImport() { assertTypeOK("module A; export X; data X; module B; export X from A; import A.X; module C; import * from B; type Y = B.X;"); } @Test public void exportQualified() { assertTypeOK("module A; export A.X; data X; module B; import X from A; type Y = X;"); } @Test public void fromImport() { assertTypeOK("module A; export X; data X; module B; import X from A; type Y = X;"); } @Test public void fromImportQualifiedUse() { assertTypeOK("module A; export X; data X; module B; import X from A; type Y = A.X;"); } @Test public void exportImportedName() { assertTypeOK("module A; export X; data X; module B; export X from A; import * from A; "); } @Test public void exportImportedName2() { assertTypeOK("module A; export X; data X; module B; export X from A; import X from A; "); } @Test public void starExportImportedNames() { assertTypeOK("module A; export *; data X; module B; export * from A; import * from A; module C; import * from B; type Y = X; "); } @Test public void starExportImportedNames2() { assertTypeOK("module A; export *; data X; module E; export *; data Z; module B; export * from E; export * from A; import * from A; import * from E; module C; import * from B; type Y = X; "); } // NEGATIVE TESTS @Test public void unqualifiedImport() { assertTypeErrors("module A; data X; module B; import X; "); } @Test public void importFromNotExistingModule() { assertTypeErrors("module B; import A.X; "); } @Test public void notExportedImport() { assertTypeErrors("module A; data X; module B; import A.X; "); } @Test public void notExportedImport2() { assertTypeErrors("module A; data X; module B; import A.X; type Y = X;"); } @Test public void notExportedImportFrom() { assertTypeErrors("module A; data X; module B; import X from A; "); } @Test public void notExportedImportFrom2() { assertTypeErrors("module A; export X; data X; data Y; module B; import X, Y from A; "); } @Test public void starImportNotExistingModule() { assertTypeErrors("module B; import * from A; "); } @Test public void qualifiedImportUnqualifiedUse() { assertTypeErrors("module A; export X; data X; module B; import A.X; type Y = X; "); } @Test public void qualifiedFromImport() { assertTypeErrors("module A; export X; data X; module B; import A.X from A; "); } @Test public void invisibleExport() { assertTypeErrors("module A; export X; "); } @Test public void exportFromNotExistingModule() { assertTypeErrors("module A; export X from B; "); } @Test public void exportNotImportedName() { assertTypeErrors("module A; export X; data X; data Y; module B; export Y from A; import * from A; "); } @Test public void invisibleExportFrom() { assertTypeErrors("module A; export X from B; "); } @Test public void ambigiousUseInterface() { // see bug #271, the reference to interface I is ambigious and should not compile assertTypeErrors("module A; export I; interface I{}" + "module B; export I; interface I{}" + "module C; import I from A; import I from B; class C implements I {} "); } @Test public void ambigiousUseInterfaceFix() { // same as above but with qualified use. This should work assertTypeOK("module A; export I; interface I{}" + "module B; export I; interface I{}" + "module C; import I from A; import I from B; class C implements A.I {} "); } @Test public void ambigiousUseData() { assertTypeErrors("module A; export I; data I = I;" + "module B; export I; data I = I;" + "module C; import I from A; import I from B; data J = J(I mmy); "); } @Test public void ambigiousUseData2() { assertTypeErrors("module A; export I; data I = I;" + "module B; export I; data I = I;" + "module C; import I from A; import I from B; data I = I; "); } @Test public void ambigiousUseClass() { assertTypeErrors("module A; export *; interface I {} class K implements I {}" + "module B; export *; interface J {} class K implements J {}" + "module C; import * from A; import * from B; { I k = new local K(); } "); } @Test public void ambigiousUseFunction() { assertTypeErrorsWithStdLib("module A; export *; def Int foo() = 3;" + "module B; export *; def Int foo() = 4;" + "module C; import * from A; import * from B; {Int x = foo(); } "); } @Test public void module_duplicate_definition() throws Exception { // don't silently overwrite imported functions etc. // https://github.com/abstools/abstools/issues/144 assertTypeErrors("module Test2; export *; def Int foo() = 42; module Test; import * from Test2; def Int foo() = 24;", Config.EXPECT_TYPE_ERROR); } @Test public void shadowImportedNames() { // see bug #271 // the definition of interface I in B should shadow the imported interface assertTypeErrorsWithStdLib("module A; export I;\n" + "interface I{ Unit a(); }\n" + "\n" + "module B; import I from A; \n" + "interface I { Unit b();}\n" + "class C implements I { Unit b() {} } \n"); } @Test public void importSameDefinitionMultipleTimes() { // Interface I is imported via M2 and via M3 but as it is the same interface this should compile assertTypeOK( "module M;" + "export *;" + "interface I {}" + "module M2;" + "export I;" + "import I from M;" + "module M3;" + "export I;" + "import I from M;" + "module Test;" + "import * from M2;" + "import * from M3;" + "class C implements I {} "); } @Test public void selfImport() { // see bug #94 assertTypeOK("module M; export X from M; import X from M; data X;"); } @Test public void circularDefinition() { assertTypeErrors("module A; export X; import X from B; module B; export X; import X from A; "); } protected void assertTypeOKWithStdLib(String absCode) { assertTypeErrors(absCode, NONE, WITH_STD_LIB); } protected void assertTypeErrorsWithStdLib(String absCode) { assertTypeErrors(absCode, EXPECT_TYPE_ERROR, WITH_STD_LIB); } protected void assertTypeOK(String absCode) { assertTypeErrors(absCode, NONE); } @Override protected SemanticCondition assertTypeErrors(String absCode) { return assertTypeErrors(absCode, EXPECT_TYPE_ERROR); } }