/* -*- tab-width: 4 -*- * * Electric(tm) VLSI Design System * * File: CodeExpressionTest.java * Written by: Dmitry Nadezhin, Sun Microsystems. * * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved. * * Electric(tm) is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * Electric(tm) 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Electric(tm); see the file COPYING. If not, write to * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, * Boston, Mass 02111-1307, USA. */ package com.sun.electric.database.variable; import com.sun.electric.database.variable.Variable.Key; import java.util.Arrays; import java.util.Collections; import java.util.Iterator; import java.util.List; import java.util.Set; import org.junit.After; import org.junit.AfterClass; import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; import static org.junit.Assert.*; /** * Unit test of CodeExpression */ public class CodeExpressionTest { public CodeExpressionTest() { } @BeforeClass public static void setUpClass() throws Exception { } @AfterClass public static void tearDownClass() throws Exception { CodeExpression.printStatistics(true); } @Before public void setUp() { } @After public void tearDown() { } /** * Test of getCFlags method, of class com.sun.electric.database.variable.AbstractTextDescriptor.Code. */ @Test public void testCodeGetCFlags() { System.out.println("getCFlags"); CodeExpression.Code instance = CodeExpression.Code.NONE; int expResult = 0; int result = instance.getCFlags(); assertEquals(expResult, result); } /** * Test of toString method, of class com.sun.electric.database.variable.AbstractTextDescriptor.Code. */ @Test public void testCodeToString() { System.out.println("toString"); CodeExpression.Code instance = CodeExpression.Code.NONE; String expResult = "Not Code"; String result = instance.toString(); assertEquals(expResult, result); } /** * Test of getCodes method, of class com.sun.electric.database.variable.AbstractTextDescriptor.Code. */ @Test public void testCodeGetCodes() { System.out.println("getCodes"); List<CodeExpression.Code> expResult = Arrays.asList( CodeExpression.Code.JAVA, CodeExpression.Code.SPICE, CodeExpression.Code.TCL, CodeExpression.Code.NONE); Iterator<CodeExpression.Code> result = CodeExpression.Code.getCodes(); int i = 0; while (result.hasNext()) { assertEquals(expResult.get(i++), result.next()); } assertEquals(expResult.size(), i); } /** * Test of getByCBits method, of class com.sun.electric.database.variable.AbstractTextDescriptor.Code. */ @Test public void testCodeGetByCBits() { System.out.println("getByCBits"); int cBits = 0; CodeExpression.Code expResult = CodeExpression.Code.NONE; CodeExpression.Code result = CodeExpression.Code.getByCBits(cBits); assertEquals(expResult, result); } /** * Test of valueOf method, of class CodeExpression. */ @Test public void valueOf() { System.out.println("valueOf"); CodeExpression ja = CodeExpression.valueOf("a", CodeExpression.Code.JAVA); assertSame(CodeExpression.Code.JAVA, ja.getCode()); assertTrue(ja.isJava()); assertEquals("a", ja.getExpr()); CodeExpression sa = CodeExpression.valueOf("a", CodeExpression.Code.SPICE); assertSame(CodeExpression.Code.SPICE, sa.getCode()); assertFalse(sa.isJava()); assertEquals("a", sa.getExpr()); CodeExpression ta = CodeExpression.valueOf("a", CodeExpression.Code.TCL); assertSame(CodeExpression.Code.TCL, ta.getCode()); assertFalse(sa.isJava()); assertEquals("a", sa.getExpr()); CodeExpression ja1 = CodeExpression.valueOf("a", CodeExpression.Code.JAVA); assertSame(ja, ja1); CodeExpression sa1 = CodeExpression.valueOf("a", CodeExpression.Code.SPICE); assertSame(sa, sa1); CodeExpression ta1 = CodeExpression.valueOf("a", CodeExpression.Code.TCL); assertSame(ta, ta1); } /** * Test of valueOf method, of class CodeExpression. */ @Test(expected = NullPointerException.class) public void valueOfNullCode() { System.out.println("valueOfNullCode"); CodeExpression.valueOf("a", null); } /** * Test of valueOf method, of class CodeExpression. */ @Test(expected = IllegalArgumentException.class) public void valueOfBadCode() { System.out.println("valueOfBadCode"); CodeExpression.valueOf("a", CodeExpression.Code.NONE); } /** * Test of dependsOn method, of class CodeExpression. */ @Test public void dependsOn() { System.out.println("dependsOn"); CodeExpression instance = CodeExpression.valueOf("@a", CodeExpression.Code.JAVA); Set<Key> expResult = Collections.singleton(Variable.newKey("ATTR_a")); Set<Key> result = instance.dependsOn(); assertEquals(expResult, result); } /** * Test of toString method, of class CodeExpression. */ @Test public void testToString() { System.out.println("toString"); assertEquals("@a", CodeExpression.valueOf("@a", CodeExpression.Code.JAVA).toString()); assertEquals("@a", CodeExpression.valueOf("@a", CodeExpression.Code.SPICE).toString()); assertEquals("@a", CodeExpression.valueOf("@a", CodeExpression.Code.TCL).toString()); } @Test public void testGoodJava() { goodJava("(@layer<4?0.04:0.056) * @L * 1e-15", "(layer<4?40m:56m)*L*1f"); goodJava("(@layer==0?0.015:@layer<6?0.025:0.030) * @L * 1e-15", "(layer==0?15m:layer<6?25m:30m)*L*1f"); goodJava("(@layer==0?6.5:@layer<4?0.084:0.0504)*@L/@width", "(layer==0?6.5:layer<4?84m:50.4m)*L/width"); goodJava("(@layer==0?7.6:@layer<6?0.086:0.036)*@L/@width", "(layer==0?7.6:layer<6?86m:36m)*L/width"); goodJava("0.8334", "0.833"); goodJava("1", "1"); goodJava("10/3.00", "10/3"); goodJava("100", "100"); goodJava("2", "2"); goodJava("2*P(\"S\")", "2*S"); goodJava("2.*@X", "2*X"); goodJava("@BF", "BF"); goodJava("@SN==0?0:@SN<1.0?(1.0*(2-0.4)/@SN + 0.4):2", "SN==0?0:SN<1?1*(2-0.4)/SN+0.4:2"); goodJava("LE.getdrive()", "LE.getdrive()"); goodJava("LE.subdrive(\"invHT1\", \"X\")", "LE.subdrive(\"invHT1\",\"X\")"); //"LE.subdrive("nand21", "X")" ? LE.subdrive(<Two operands with no operator>"nand21", "X") -> "LE.subdrive(<Two operands with no operator>"nand21", "X")" //"LE.subdrive("nand2_sy1", "X")" ? LE.subdrive(<Two operands with no operator>"nand2_sy1", "X") -> "LE.subdrive(<Two operands with no operator>"nand2_sy1", "X")" //"LE.subdrive("nor21", "X")" ? LE.subdrive(<Two operands with no operator>"nor21", "X") -> "LE.subdrive(<Two operands with no operator>"nor21", "X")" //"LE.subdrive("nor2_sy1", "S")" ? LE.subdrive(<Two operands with no operator>"nor2_sy1", "S") -> "LE.subdrive(<Two operands with no operator>"nor2_sy1", "S")" goodJava("Math.max(((Number)@X).doubleValue()/10., 5./3.)", "max(X/10,5/3)"); //"Math.max(((Number)@X).doubleValue()/10., 5./6.)" ATTR_X ? Math.max(<Two operands with no operator>((Number)P("ATTR_X")).doubleValue()/10., 5./6.) -> "Math.max(<Two operands with no operator>((Number)P("ATTR_X")).doubleValue()/10., 5./6.)" //"P("L")" ATTR_L ? P("ATTR_L"<Illegal character ">) -> "P("ATTR_L"<Illegal character ">)" //"P("L")/2.0" ATTR_L ? P("ATTR_L"<Illegal character ">)/2.0 -> "P("ATTR_L"<Illegal character ">)/2.0" //"P("S")" ATTR_S ? P("ATTR_S"<Illegal character ">) -> "P("ATTR_S"<Illegal character ">)" //"P("SN")>0.5?6*P("SN"):3" ATTR_SN ? P("ATTR_SN"<Illegal character ">)>0.5?6*P("ATTR_SN"):3 -> "P("ATTR_SN"<Illegal character ">)>0.5?6*P("ATTR_SN"):3" //"P("SN")>1?3*P("SN"):3" ATTR_SN ? P("ATTR_SN"<Illegal character ">)>1?3*P("ATTR_SN"):3 -> "P("ATTR_SN"<Illegal character ">)>1?3*P("ATTR_SN"):3" //"P("SP")>0.5?6*P("SP"):3" ATTR_SP ? P("ATTR_SP"<Illegal character ">)>0.5?6*P("ATTR_SP"):3 -> "P("ATTR_SP"<Illegal character ">)>0.5?6*P("ATTR_SP"):3" //"P("W")" ATTR_W ? P("ATTR_W"<Illegal character ">) -> "P("ATTR_W"<Illegal character ">)" //"P("W")<1?2.0/P("W"):2" ATTR_W ? P("ATTR_W"<Illegal character ">)<1?2.0/P("ATTR_W"):2 -> "P("ATTR_W"<Illegal character ">)<1?2.0/P("ATTR_W"):2" //"P("W")>1?3*P("W"):3" ATTR_W ? P("ATTR_W"<Illegal character ">)>1?3*P("ATTR_W"):3 -> "P("ATTR_W"<Illegal character ">)>1?3*P("ATTR_W"):3" //"Pfingers=Math.ceil(2.*@X.doubleValue()/15.); (2.*(Pfingers + 1.0) * 13.0 + @X*4.5) / 4." ATTR_X ? Pfingers=Math.ceil(<Expected token ==>2.*P("ATTR_X").doubleValue()/15.); (2.*(Pfingers + 1.0) * 13.0 + P("ATTR_X")*4.5) / 4. -> "Pfingers=Math.ceil(<Expected token ==>2.*P("ATTR_X").doubleValue()/15.); (2.*(Pfingers + 1.0) * 13.0 + P("ATTR_X")*4.5) / 4." //"Pfingers=Math.ceil(2.*@X.doubleValue()/15.); (2.*(Pfingers + 1.0) * 13.0 + @X*6.)/4." ATTR_X ? Pfingers=Math.ceil(<Expected token ==>2.*P("ATTR_X").doubleValue()/15.); (2.*(Pfingers + 1.0) * 13.0 + P("ATTR_X")*6.)/4. -> "Pfingers=Math.ceil(<Expected token ==>2.*P("ATTR_X").doubleValue()/15.); (2.*(Pfingers + 1.0) * 13.0 + P("ATTR_X")*6.)/4." //"Pfingers=Math.ceil(2.*@X.doubleValue()/15.); (Pfingers + 1.0) * 13.0" ATTR_X ? Pfingers=Math.ceil(<Expected token ==>2.*P("ATTR_X").doubleValue()/15.); (Pfingers + 1.0) * 13.0 -> "Pfingers=Math.ceil(<Expected token ==>2.*P("ATTR_X").doubleValue()/15.); (Pfingers + 1.0) * 13.0" //"Pfingers=Math.ceil(2.*@X.doubleValue()/15.); (Pfingers + 1.0) * 8.0 + (Pfingers*1.5) * 5." ATTR_X ? Pfingers=Math.ceil(<Expected token ==>2.*P("ATTR_X").doubleValue()/15.); (Pfingers + 1.0) * 8.0 + (Pfingers*1.5) * 5. -> "Pfingers=Math.ceil(<Expected token ==>2.*P("ATTR_X").doubleValue()/15.); (Pfingers + 1.0) * 8.0 + (Pfingers*1.5) * 5." } private void goodJava(String expr, String expected) { CodeExpression ce = CodeExpression.valueOf(expr, CodeExpression.Code.JAVA); assertNull(ce.getParseException()); assertEquals(expected, ce.getSpiceText()); } @Test public void testGoodSpice() { System.out.println("goodSpice"); goodSpice("1 + 2", "1+2"); goodSpice("1 + 2 * 3", "1+2*3"); goodSpice("1 * 2 + 3", "1*2+3"); goodSpice("(1 + 2) * 3", "(1+2)*3"); goodSpice("(1 + 2) * X", "(1+2)*X"); goodSpice("300 / -1.5e2", "300/-150"); goodSpice("1.5e-2", "15m"); goodSpice("20 * 1.5e-2", "20*15m"); goodSpice("20 * 1.5m", "20*1.5m"); goodSpice("(1 + a) * 3 + b", "(1+a)*3+b"); goodSpice("1 + 2 * 3 + - 4", "1+2*3+-4"); goodSpice("-1", "-1"); goodSpice("-1 + 2 * 3 + - 4", "-1+2*3+-4"); goodSpice("-(1 + 2) * 3 + -4", "-(1+2)*3+-4"); goodSpice("-(1 + 2) * 3 + -4 * -2 - -4 * -3", "-(1+2)*3+-4*-2--4*-3"); goodSpice("-sin(3)", "-sin(3)"); goodSpice("-sin(X)", "-sin(X)"); goodSpice("1-min(1,-2)", "1-min(1,-2)"); goodSpice("1-min(1,X)", "1-min(1,X)"); goodSpice("1-min((a+b)*c,X)", "1-min((a+b)*c,X)"); goodSpice("1-min((a+b)*c,(a+b))", "1-min((a+b)*c,a+b)"); goodSpice("-a + 2 * 3 * -b + - 4", "-a+2*3*-b+-4"); goodSpice("1 ? -2 : 4", "1?-2:4"); goodSpice("0 ? -2 : 4", "0?-2:4"); goodSpice("8 == 1 ? -2 : 4", "8==1?-2:4"); goodSpice("8 > 1 ? -2 : 4", "8>1?-2:4"); goodSpice("1 - 7 <= 1 ? -2 : 4", "1-7<=1?-2:4"); goodSpice("layer == 1 ? two + 1 : eight * 4 / 2", "layer==1?two+1:eight*4/2"); goodSpice("0 * 1 ? 3 / 2 : -4 + 10", "0*1?3/2:-4+10"); goodSpice("(3==0?0.00441:3<8?0.011:0.016)*1e-15", "(3==0?4.41m:3<8?11m:16m)*1f"); goodSpice("(layer==0?0.00441:layer<8?0.011:0.016)*1e-15", "(layer==0?4.41m:layer<8?11m:16m)*1f"); goodSpice("1/0", "1/0"); } private void goodSpice(String expr, String expected) { CodeExpression ce = CodeExpression.valueOf(expr, CodeExpression.Code.SPICE); assertNull(ce.getParseException()); assertEquals(expected, ce.getSpiceText()); } @Test public void testBadSpice() { System.out.println("badSpice"); badSpice("", "<Expected identifier>"); badSpice("%", "%<Illegal character %>"); badSpice("-", "-<Expected identifier>"); badSpice("+", "+<Operator + with no left hand operand>"); badSpice("1+", "1+<Expected identifier>"); badSpice("+1", "+<Operator + with no left hand operand>1"); badSpice("1 1", "1 1<Two operands with no operator>"); badSpice("1 + + 1", "1 + +<Operator + with no left hand operand> 1"); badSpice("(", "(<Expected identifier>"); badSpice("(a", "(a<Expected token )>"); badSpice(")", ")<Expected identifier>"); badSpice("a a", "a a<Two operands with no operator>"); badSpice("sin x", "sin x<Expected token (>"); // From EvalSpice test badSpice("1 2 +", "1 2 <Two operands with no operator>+"); badSpice("1 + * 2", "1 + *<Operator * with no left hand operand> 2"); badSpice("1 + 2 * - -3", "1 + 2 * - -<Operator - with no left hand operand>3"); badSpice("300 / -1.5ee2 + 5", "300 / -1.5ee<Invalid token>2 + 5"); badSpice("1-min((a+b)*c,(a+b)", "1-min((a+b)*c,(a+b)<Expected token )>"); badSpice("M1 - M3 : 10001", "M1 - M3 :<Unexpected character :> 10001"); } private void badSpice(String expr, String expected) { CodeExpression ce = CodeExpression.valueOf(expr, CodeExpression.Code.SPICE); assertEquals(expected, ce.getParseException().getMessage()); } /** * Test written by Jonathan Gainsley for EvalSpice class */ @Test public void testJonG() { System.out.println("Jon's test"); testEval("1 + 2", 3); testEval("1 + 2 * 3", 7); testEval("1 * 2 + 3", 5); testEval("(1 + 2) * 3", 9); testEval("(1 + 2) * x", "3 * x"); testEval("300 / -1.5e2", -2); testEval("1.5e-2", 0.015); testEval("20 * 1.5e-2", 0.3); testEval("20 * 1.5m", 0.03); testEval("(1 + a) * 3 + b", "(1 + a) * 3 + b"); testEval("1 + 2 * 3 + - 4", 3); testEval("-1", -1); testEval("-1 + 2 * 3 + - 4", 1); testEval("-(1 + 2) * 3 + -4", -13); testEval("-(1 + 2) * 3 + -4 * -2 - -4 * -3", -13); testEval("-sin(3)", -Math.sin(3)); testEval("-sin(x)", "-sin(x)"); testEval("1-min(1,-2)", 3); testEval("1-min(1,x)", null); testEval("1-min((a+b)*c,x)", null); testEval("1-min((a+b)*c,(a+b))", null); testEval("-a + 2 * 3 * -b + - 4", null); testEval("1 ? -2 : 4", -2); testEval("0 ? -2 : 4", 4); testEval("8 == 1 ? -2 : 4", 4); testEval("8 > 1 ? -2 : 4", -2); testEval("1 - 7 <= 1 ? -2 : 4", -2); testEval("layer == 1 ? two + 1 : eight * 4 / 2", "layer == 1 ? two + 1 : eight * 4 / 2"); testEval("0 * 1 ? 3 / 2 : -4 + 10", 6); testEval("(3==0?0.00441:3<8?0.011:0.016)*1e-15", 1.1e-17); testEval("(layer==0?0.00441:layer<8?0.011:0.016)*1e-15", null); System.out.println("\nThese should flag as errors:\n---------------------------\n"); testEval("1 2 +", null); testEval("1 + * 2", null); testEval("1 + 2 * - -3", null); testEval("300 / -1.5ee2 + 5", null); testEval("1-min((a+b)*c,(a+b)", null); testEval("1/0", null); testEval("M1 - M3 : 10001", null); } private void testEval(String expr, String expected) { // CodeExpression ce = CodeExpression.valueOf(expr, false); // String evald = ce.eval().toString(); // if (expected == null) { // System.out.println(expr+" = "+evald); // } else { // System.out.println(expr+" = "+evald+" -- ("+expected+")"); // assertEquals(expected, evald); // } } private void testEval(String expr, double expected) { CodeExpression ce = CodeExpression.valueOf(expr, CodeExpression.Code.SPICE); assertNull(ce.getParseException()); Double result = (Double) ce.eval(); assertEquals(expected, result, 0); } }