/* * Copyright 2009 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.common.css.compiler.passes; import static org.easymock.EasyMock.capture; import static org.easymock.EasyMock.createMock; import static org.easymock.EasyMock.eq; import static org.easymock.EasyMock.expect; import static org.easymock.EasyMock.replay; import static org.easymock.EasyMock.verify; import com.google.common.css.SourceCodeLocation; import com.google.common.css.compiler.ast.BackDoorNodeMutation; import com.google.common.css.compiler.ast.CssBlockNode; import com.google.common.css.compiler.ast.CssCompositeValueNode; import com.google.common.css.compiler.ast.CssConstantReferenceNode; import com.google.common.css.compiler.ast.CssDeclarationNode; import com.google.common.css.compiler.ast.CssDefinitionNode; import com.google.common.css.compiler.ast.CssLiteralNode; import com.google.common.css.compiler.ast.CssNode; import com.google.common.css.compiler.ast.CssNumericNode; import com.google.common.css.compiler.ast.CssPropertyNode; import com.google.common.css.compiler.ast.CssPropertyValueNode; import com.google.common.css.compiler.ast.CssRootNode; import com.google.common.css.compiler.ast.CssRulesetNode; import com.google.common.css.compiler.ast.CssSelectorNode; import com.google.common.css.compiler.ast.CssTree; import com.google.common.css.compiler.ast.ErrorManager; import com.google.common.css.compiler.ast.GssError; import com.google.common.css.compiler.ast.MutatingVisitController; import junit.framework.TestCase; import org.easymock.Capture; import org.easymock.EasyMock; import java.util.List; /** * Unit tests for {@link ReplaceConstantReferences}. * * @author oana@google.com (Oana Florescu) */ public class ReplaceConstantReferencesTest extends TestCase { public void testRunPass() { MutatingVisitController visitController = createMock( MutatingVisitController.class); CssTree tree = createMock(CssTree.class); expect(tree.getMutatingVisitController()) .andReturn(visitController).anyTimes(); // We need to have this replayed because in the constructor of // ReplaceConstantReferences pass we need tree.getMutatingVisitController(). replay(tree); ReplaceConstantReferences pass = new ReplaceConstantReferences(tree, new ConstantDefinitions(), true /* removeDefs */, new DummyErrorManager(), true /* allowUndefinedConstants */); visitController.startVisit(pass); replay(visitController); pass.runPass(); verify(visitController); } public void testEnterDefinitionNode() { MutatingVisitController visitController = createMock( MutatingVisitController.class); CssTree tree = createMock(CssTree.class); expect(tree.getMutatingVisitController()) .andReturn(visitController).anyTimes(); // We need to have this replayed because in the constructor of // ReplaceConstantReferences pass we need tree.getMutatingVisitController(). replay(tree); ReplaceConstantReferences pass = new ReplaceConstantReferences(tree, new ConstantDefinitions(), true /* removeDefs */, new DummyErrorManager(), true /* allowUndefinedConstants */); visitController.removeCurrentNode(); replay(visitController); CssDefinitionNode node = new CssDefinitionNode(new CssLiteralNode("COLOR")); pass.enterDefinition(node); verify(visitController); } public void testEnterValueNode() { CssDefinitionNode def = new CssDefinitionNode(new CssLiteralNode("COLOR")); def.getParameters().add(new CssLiteralNode("red")); CssPropertyNode prop1 = new CssPropertyNode("padding", null); CssPropertyValueNode value1 = new CssPropertyValueNode(); BackDoorNodeMutation.addChildToBack(value1, new CssNumericNode("5", "px")); CssPropertyNode prop2 = new CssPropertyNode("color", null); CssPropertyValueNode value2 = new CssPropertyValueNode(); CssConstantReferenceNode ref = new CssConstantReferenceNode("COLOR", null); BackDoorNodeMutation.addChildToBack(value2, ref); CssDeclarationNode decl1 = new CssDeclarationNode(prop1); decl1.setPropertyValue(value1); CssDeclarationNode decl2 = new CssDeclarationNode(prop2); decl2.setPropertyValue(value2); CssRulesetNode ruleset = new CssRulesetNode(); CssSelectorNode sel = new CssSelectorNode("foo", null); ruleset.addSelector(sel); ruleset.addDeclaration(decl1); ruleset.addDeclaration(decl2); CssBlockNode body = new CssBlockNode(false); BackDoorNodeMutation.addChildToBack(body, ruleset); CssRootNode root = new CssRootNode(body); CssTree tree = new CssTree(null, root); ConstantDefinitions constantDefinitions = new ConstantDefinitions(); constantDefinitions.addConstantDefinition(def); ReplaceConstantReferences pass = new ReplaceConstantReferences(tree, constantDefinitions, true /* removeDefs */, new DummyErrorManager(), true /* allowUndefinedConstants */); pass.runPass(); assertEquals(tree.getRoot().getBody().toString(), "[[foo]{[padding:[5px], color:[red]]}]"); } // TODO(oana): Added a task in tracker for fixing these dependencies and // making the mocking of objects easier. public void testEnterArgumentNode() { CssDefinitionNode def = new CssDefinitionNode(new CssLiteralNode("COLOR")); MutatingVisitController visitController = createMock( MutatingVisitController.class); CssTree tree = createMock(CssTree.class); expect(tree.getMutatingVisitController()) .andReturn(visitController).anyTimes(); ConstantDefinitions definitions = EasyMock.createMock( ConstantDefinitions.class); expect(definitions.getConstantDefinition("COLOR")) .andReturn(def).anyTimes(); replay(definitions); replay(tree); ReplaceConstantReferences pass = new ReplaceConstantReferences(tree, definitions, true /* removeDefs */, new DummyErrorManager(), true /* allowUndefinedConstants */); Capture<List<CssNode>> tempList = new Capture<List<CssNode>>(); visitController.replaceCurrentBlockChildWith(capture(tempList), eq(true)); replay(visitController); CssConstantReferenceNode node = new CssConstantReferenceNode("COLOR", null); pass.enterArgumentNode(node); verify(visitController); assertEquals(1, tempList.getValue().size()); assertEquals( CssCompositeValueNode.class, tempList.getValue().get(0).getClass()); } public void testAllowUndefinedConstants() { ConstantDefinitions definitions = EasyMock.createMock( ConstantDefinitions.class); expect(definitions.getConstantDefinition("Foo")).andStubReturn(null); SourceCodeLocation loc = createMock(SourceCodeLocation.class); CssConstantReferenceNode refNode = createMock( CssConstantReferenceNode.class); expect(refNode.getValue()).andStubReturn("Foo"); expect(refNode.getSourceCodeLocation()).andStubReturn(loc); // This should not cause an error to be reported. ErrorManager errorManager = createMock(ErrorManager.class); replay(definitions, refNode, errorManager); ReplaceConstantReferences allowingPass = new ReplaceConstantReferences(createMock(CssTree.class), definitions, true /* removeDefs */, errorManager, true /* allowUndefinedConstants */); allowingPass.replaceConstantReference(refNode); verify(definitions, refNode, errorManager); } public void testAllowUndefinedConstantsError() { ConstantDefinitions definitions = EasyMock.createMock( ConstantDefinitions.class); expect(definitions.getConstantDefinition("Foo")).andStubReturn(null); SourceCodeLocation loc = createMock(SourceCodeLocation.class); CssConstantReferenceNode refNode = createMock( CssConstantReferenceNode.class); expect(refNode.getValue()).andStubReturn("Foo"); expect(refNode.getSourceCodeLocation()).andStubReturn(loc); // This should cause an error to be reported. ErrorManager errorManager = createMock(ErrorManager.class); errorManager.report(EasyMock.<GssError>anyObject()); replay(definitions, refNode, errorManager); ReplaceConstantReferences nonAllowingPass = new ReplaceConstantReferences(createMock(CssTree.class), definitions, true /* removeDefs */, errorManager, false /* allowUndefinedConstants */); nonAllowingPass.replaceConstantReference(refNode); verify(definitions, refNode, errorManager); } }