/*
* ******************************************************************************
* MontiCore Language Workbench
* Copyright (c) 2015, MontiCore, All rights reserved.
*
* This project is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3.0 of the License, or (at your option) any later version.
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this project. If not, see <http://www.gnu.org/licenses/>.
* ******************************************************************************
*/
package mc.feature.cocochecker;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import java.io.IOException;
import java.io.StringReader;
import java.util.Optional;
import org.junit.Before;
import org.junit.Test;
import mc.GeneratorIntegrationsTest;
import mc.feature.cocochecker.a._ast.ASTANode;
import mc.feature.cocochecker.a._ast.ASTX;
import mc.feature.cocochecker.a._cocos.AASTXCoCo;
import mc.feature.cocochecker.a._cocos.ACoCoChecker;
import mc.feature.cocochecker.a._parser.AParser;
import mc.feature.cocochecker.b._cocos.BASTXCoCo;
import mc.feature.cocochecker.b._cocos.BASTYCoCo;
import mc.feature.cocochecker.b._cocos.BCoCoChecker;
import mc.feature.cocochecker.c._cocos.CASTXCoCo;
import mc.feature.cocochecker.c._cocos.CASTZCoCo;
import mc.feature.cocochecker.c._cocos.CCoCoChecker;
/**
* Tests adding cocos of super languages to a checker of a sublanguage.<br/>
* <br/>
* X is defined in C and B. A extends C and B and overrides X, so CoCos defined
* for X are only checked if they are defined for the X from language A and its
* supertypes (hence, also the cocos added for X from C are checked).<br/>
* In contrast, the cocos defined for Y (from B) and Z (from C) must be checked!<br/>
* <br/>
* The tests in this test suite ensure that this happens for composing all the
* cocos within the checker of A as well as for composing the cocos in their
* language's checkers and then composing the checkers in A's checker.
*
* @author Robert Heim
*/
public class CoCoCheckerTest extends GeneratorIntegrationsTest {
final StringBuilder checked = new StringBuilder();
final private AASTXCoCo cocoA = new AASTXCoCo() {
@Override
public void check(ASTX node) {
checked.append("A");
}
};
final private BASTXCoCo cocoB = new BASTXCoCo() {
@Override
public void check(mc.feature.cocochecker.b._ast.ASTX node) {
checked.append("B");
}
};
final private BASTYCoCo cocoY = new BASTYCoCo() {
@Override
public void check(mc.feature.cocochecker.b._ast.ASTY node) {
checked.append("Y");
}
};
final private CASTXCoCo cocoC = new CASTXCoCo() {
@Override
public void check(mc.feature.cocochecker.c._ast.ASTX node) {
checked.append("C");
}
};
final private CASTZCoCo cocoZ = new CASTZCoCo() {
@Override
public void check(mc.feature.cocochecker.c._ast.ASTZ node) {
checked.append("Z");
}
};
// the ast used for testing.
private ASTANode ast;
@Before
public void setUp() {
Optional<ASTX> astOpt = Optional.empty();
try {
astOpt = new AParser().parseX(new StringReader("xyz"));
}
catch (IOException e) {
e.printStackTrace();
fail("Parser Error.");
}
assertTrue(astOpt.isPresent());
ast = astOpt.get();
checked.setLength(0);
}
@Test
public void testCoCoComposition() {
ACoCoChecker checker = new ACoCoChecker();
checker.addCoCo(cocoA);
checker.addCoCo(cocoB);
checker.addCoCo(cocoY);
checker.addCoCo(cocoC);
checker.addCoCo(cocoZ);
checker.checkAll(ast);
assertEquals("BAYZ", checked.toString());
}
@Test
public void testCheckerComposition() {
ACoCoChecker checkerA = new ACoCoChecker();
checkerA.addCoCo(cocoA);
BCoCoChecker checkerB = new BCoCoChecker();
checkerB.addCoCo(cocoB);
checkerB.addCoCo(cocoY);
CCoCoChecker checkerC = new CCoCoChecker();
checkerC.addCoCo(cocoC);
checkerC.addCoCo(cocoZ);
// compose existing checkers
checkerA.addChecker(checkerB);
checkerA.addChecker(checkerC);
checkerA.checkAll(ast);
assertEquals("BAYZ", checked.toString());
}
}