/* * Copyright 2010 The Closure Compiler Authors. * * 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.javascript.jscomp.jsonml; import com.google.javascript.jscomp.jsonml.JsonML; import com.google.javascript.jscomp.jsonml.JsonMLUtil; import com.google.javascript.jscomp.jsonml.TagAttr; import com.google.javascript.jscomp.jsonml.TagType; import com.google.javascript.jscomp.jsonml.Validator; import junit.framework.TestCase; /** * Tests validation of particular JsonML elements. * * @author dhans@google.com (Daniel Hans) */ public class JsonMLValidationTest extends TestCase { // Used for correct statements - error message should be null private void testValidation(String jsonml) throws Exception { JsonML jsonMLRoot = JsonMLUtil.parseString(jsonml); String msg = Validator.validate(jsonMLRoot); if (msg != null) { String errorMsg = String.format( "Validation error for %s.\n Received: %s\n", jsonml, msg); } } private void testValidation(String jsonml, String expected) throws Exception { JsonML jsonMLRoot = JsonMLUtil.parseString(jsonml); String msg = Validator.validate(jsonMLRoot); if (!msg.equals(expected)) { String errorMsg = String.format( "Validation error for %s.\n Received: %s\n Expected: %s\n", jsonml, msg, expected); assertEquals(errorMsg, expected, msg); } } private void testNotEnoughChildrenValidation(String jsonml, TagType type, int expected, int actual) throws Exception { testValidation(jsonml, String.format(Validator.NOT_ENOUGH_CHILDREN_FMT, type, expected, actual)); } private void testTooManyChildrenValidation(String jsonml, TagType type, int expected, int actual) throws Exception { testValidation(jsonml, String.format(Validator.TOO_MANY_CHILDREN_FMT, type, expected, actual)); } private void testWrongChildTypeValidation(String jsonml, TagType type, TagType expected, TagType actual, int index) throws Exception { testWrongChildTypeValidation(jsonml, type, new TagType[] { expected }, actual, index); } private void testWrongChildTypeValidation(String jsonml, TagType type, TagType[] expected, TagType actual, int index) throws Exception { testValidation(jsonml, String.format(Validator.WRONG_CHILD_TYPE_FMT, index, type, Validator.printList(expected), actual)); } private void testMissingArgument(String jsonml, TagAttr attr, TagType type) throws Exception { testValidation(jsonml, String.format(Validator.MISSING_ARGUMENT, attr, type)); } public void testAssignExpr() throws Exception { // correct statement testValidation("" + "['AssignExpr',{'op':'='}," + "['IdExpr',{'name':'x'}]," + "['LiteralExpr',{'type':'number','value':1}]]"); // wrong number of children testNotEnoughChildrenValidation("" + "['AssignExpr',{'op':'='}," + "['IdExpr',{'name':'x'}]]", TagType.AssignExpr, 2, 1); testTooManyChildrenValidation("" + "['AssignExpr',{'op':'='}," + "['IdExpr',{'name':'x'}]," + "['IdExpr',{'name':'y'}]," + "['IdExpr',{'name':'z'}]]", TagType.AssignExpr, 2, 3); // missing attribute testMissingArgument("" + "['AssignExpr',{}," + "['IdExpr',{'name':'x'}]," + "['LiteralExpr',{'type':'number','value':1}]]", TagAttr.OP, TagType.AssignExpr); } public void testBinaryExpr() throws Exception { // correct statement testValidation("" + "['BinaryExpr',{'op':'+'}," + "['IdExpr',{'name':'a'}]," + "['LiteralExpr',{'type':'number','value':1}]]"); // wrong number of children testNotEnoughChildrenValidation("" + "['BinaryExpr',{'op':'+'}," + "['IdExpr',{'name':'a'}]]", TagType.BinaryExpr, 2, 1); testTooManyChildrenValidation("" + "['BinaryExpr',{'op':'&&'}," + "['IdExpr',{'name':'a'}]," + "['IdExpr',{'name':'b'}]," + "['IdExpr',{'name':'c'}]]", TagType.BinaryExpr, 2, 3); // missing attribute testMissingArgument("" + "['BinaryExpr',{}," + "['IdExpr',{'name':'a'}]," + "['LiteralExpr',{'type':'number','value':1}]]", TagAttr.OP, TagType.BinaryExpr); } public void testCaseValidation() throws Exception { // correct statement testValidation("" + "['Case',{}," + "['IdExpr',{'name':'a'}]]"); testValidation("" + "['Case',{}," + "['IdExpr',{'name':'a'}]," + "['CallExpr',{}," + "['IdExpr',{'name':'foo'}]]]"); // wrong number of children testNotEnoughChildrenValidation("" + "['Case',{}]", TagType.Case, 1, 0); } public void testCatchValidation() throws Exception { // correct statement testValidation("" + "['CatchClause',{}," + "['IdPatt',{'name':'e'}]," + "['BlockStmt',{}]]"); // wrong number of children testNotEnoughChildrenValidation("" + "['CatchClause',{}," + "['IdPatt',{'name':'e'}]]", TagType.CatchClause, 2, 1); // wrong children types testWrongChildTypeValidation("" + "['CatchClause',{}," + "['IdExpr',{'name':'e'}]," + "['BlockStmt',{}]]", TagType.CatchClause, TagType.IdPatt, TagType.IdExpr, 0); } public void testConditionalExprValidation() throws Exception { // correct statement testValidation("" + "['ConditionalExpr',{}," + "['BinaryExpr',{'op':'=='}," + "['IdExpr',{'name':'x'}]," + "['LiteralExpr',{'type':'number','value':0}]]," + "['LiteralExpr',{'type':'number','value':0}]," + "['LiteralExpr',{'type':'number','value':1}]]"); // wrong number of children testNotEnoughChildrenValidation("" + "['ConditionalExpr',{}," + "['BinaryExpr',{'op':'=='}," + "['IdExpr',{'name':'x'}]," + "['LiteralExpr',{'type':'number','value':0}]]]", TagType.ConditionalExpr, 3, 1); testNotEnoughChildrenValidation("" + "['ConditionalExpr',{}," + "['BinaryExpr',{'op':'=='}," + "['IdExpr',{'name':'x'}]," + "['LiteralExpr',{'type':'number','value':0}]]," + "['LiteralExpr',{'type':'number','value':1}]]", TagType.ConditionalExpr, 3, 2); } public void testCountExprValidation() throws Exception { // correct statement testValidation("" + "['CountExpr',{'isPrefix':false,'op':'++'}," + "['IdExpr',{'name':'x'}]]"); // wrong number of children testTooManyChildrenValidation("" + "['CountExpr',{'isPrefix':false,'op':'++'}," + "['IdExpr',{'name':'x'}]," + "['IdExpr',{'name':'y'}]]", TagType.CountExpr, 1, 2); // missing attribute testMissingArgument("" + "['CountExpr',{'op':'++'}," + "['IdExpr',{'name':'x'}]]", TagAttr.IS_PREFIX, TagType.CountExpr); testMissingArgument("" + "['CountExpr',{'isPrefix':false}," + "['IdExpr',{'name':'x'}]]", TagAttr.OP, TagType.CountExpr); } public void testDataProp() throws Exception { // correct statement testValidation("" + "['DataProp',{'name':'x'}," + "['LiteralExpr',{'type':'number','value':1}]]"); // wrong number of children testNotEnoughChildrenValidation("" + "['DataProp',{'name':'x'}]", TagType.DataProp, 1, 0); // missing argument testMissingArgument("" + "['DataProp', {}," + "['LiteralExpr',{'type':'number','value':1}]]", TagAttr.NAME, TagType.DataProp); } public void testDeleteExpr() throws Exception { // correct statement testValidation("" + "['DeleteExpr',{}," + "['IdExpr',{'name':'x'}]]"); //wrong number of children testNotEnoughChildrenValidation("" + "['DeleteExpr',{}]", TagType.DeleteExpr, 1, 0); testTooManyChildrenValidation("" + "['DeleteExpr',{}," + "['IdExpr',{'name':'x'}]," + "['IdExpr',{'name':'y'}]]", TagType.DeleteExpr, 1, 2); } public void testDoWhileStmtValidation() throws Exception { // correct statement testValidation("" + "['DoWhileStmt',{}," + "['BlockStmt',{}]," + "['LiteralExpr',{'type':'boolean','value':true}]]"); // wrong number of children testNotEnoughChildrenValidation("" + "['DoWhileStmt',{}]", TagType.DoWhileStmt, 2, 0); testTooManyChildrenValidation("" + "['DoWhileStmt',{}," + "['BlockStmt',{}]," + "['BlockStmt',{}]," + "['LiteralExpr',{'type':'boolean','value':true}]]", TagType.DoWhileStmt, 2, 3); } public void testEmptyStmtValidation() throws Exception { // correct statement testValidation("" + "['EmptyStmt',{}]"); // wrong number of children testTooManyChildrenValidation("" + "['EmptyStmt',{}," + "['BlockStmt',{}]]", TagType.EmptyStmt, 0, 1); } public void testForInStmtValidation() throws Exception { // correct statement testValidation("" + "['ForInStmt',{}," + "['IdExpr',{'name':'x'}]," + "['ObjectExpr',{}]," + "['BlockStmt',{}]]"); // wrong number of children testNotEnoughChildrenValidation("" + "['ForInStmt',{}," + "['IdExpr',{'name':'x'}]," + "['ObjectExpr',{}]],", TagType.ForInStmt, 3, 2); testTooManyChildrenValidation("" + "['ForInStmt',{}," + "['IdExpr',{'name':'x'}]," + "['ObjectExpr',{}]," + "['BlockStmt',{}]," + "['BlockStmt',{}]]", TagType.ForInStmt, 3, 4); } public void testForStmtValidation() throws Exception { // correct statement testValidation("" + "['ForStmt',{}," + "['AssignExpr',{'op':'='}," + "['IdExpr',{'name':'i'}]," + "['LiteralExpr',{'type':'number','value':0}]]," + "['BinaryExpr',{'op':'<'}," + "['IdExpr',{'name':'i'}]," + "['IdExpr',{'name':'n'}]]," + "['CountExpr',{'isPrefix':true,'op':'++'}," + "['IdExpr',{'name':'i'}]]," + "['BlockStmt',{}]]"); // wrong number of children testNotEnoughChildrenValidation("" + "['ForStmt',{}," + "['BinaryExpr',{'op':'<'}," + "['IdExpr',{'name':'i'}]," + "['IdExpr',{'name':'n'}]]," + "['CountExpr',{'isPrefix':true,'op':'++'}," + "['IdExpr',{'name':'i'}]]," + "['BlockStmt',{}]]", TagType.ForStmt, 4, 3); testTooManyChildrenValidation("" + "['ForStmt',{}," + "['AssignExpr',{'op':'='}," + "['IdExpr',{'name':'i'}]," + "['LiteralExpr',{'type':'number','value':0}]]," + "['BinaryExpr',{'op':'<'}," + "['IdExpr',{'name':'i'}]," + "['IdExpr',{'name':'n'}]]," + "['CountExpr',{'isPrefix':true,'op':'++'}," + "['IdExpr',{'name':'i'}]]," + "['BlockStmt',{}]," + "['BlockStmt',{}]]", TagType.ForStmt, 4, 5); } public void testFunctionDeclValidation() throws Exception { // correct statement testValidation("" + "['FunctionDecl',{}," + "['IdPatt',{'name':'f'}]," + "['ParamDecl',{}]]"); testValidation("" + "['FunctionDecl',{}," + "['IdPatt',{'name':'f'}]," + "['ParamDecl',{}]," + "['IdExpr',{'name':'foo'}]]"); // wrong number of children testNotEnoughChildrenValidation("" + "['FunctionDecl',{}," + "['IdPatt',{'name':'f'}]]", TagType.FunctionDecl, 2, 1); // function name not specified testWrongChildTypeValidation("" + "['FunctionDecl',{}," + "['Empty', {}]," + "['ParamDecl',{}]]", TagType.FunctionDecl, TagType.IdPatt, TagType.Empty, 0); // list of formal arguments not specified testWrongChildTypeValidation("" + "['FunctionDecl',{}," + "['IdPatt',{'name':'f'}]," + "['Empty',{}]]", TagType.FunctionDecl, TagType.ParamDecl, TagType.Empty, 1); } public void testFunctionExprValidation() throws Exception { // correct statement testValidation("" + "['FunctionExpr',{}," + "['IdPatt',{'name':'f'}]," + "['ParamDecl',{}]]"); testValidation("" + "['FunctionExpr',{}," + "['IdPatt',{'name':'f'}]," + "['ParamDecl',{}]," + "['IdExpr',{'name':'foo'}]]"); testValidation("" + "['FunctionExpr',{}," + "['Empty', {}]," + "['ParamDecl',{}]]"); } public void testIdExprValidation() throws Exception { // correct statement testValidation("" + "['IdExpr',{'name':'x'}]"); // wrong number of children testTooManyChildrenValidation("" + "['IdExpr',{'name':'x'}," + "['BlockStmt',{}]]", TagType.IdExpr, 0, 1); // missing name argument testMissingArgument("" + "['IdExpr', {}]", TagAttr.NAME, TagType.IdExpr); } public void testIdPattValidation() throws Exception { // correct statement testValidation("" + "['IdPatt',{'name':'x'}]"); // wrong number of children testTooManyChildrenValidation("" + "['IdPatt',{'name':'x'}," + "['BlockStmt',{}]]", TagType.IdPatt, 0, 1); // missing name argument testMissingArgument("" + "['IdPatt', {}]", TagAttr.NAME, TagType.IdPatt); } public void testIfStmtValidation() throws Exception { // correct statement testValidation("" + "['IfStmt',{}," + "['LiteralExpr',{'type':'boolean','value':true}]," + "['BlockStmt',{}]," + "['EmptyStmt',{}]]"); testValidation("" + "['IfStmt',{}," + "['LiteralExpr',{'type':'boolean','value':true}]," + "['BlockStmt',{}]," + "['BlockStmt',{}]]"); // wrong number of children testNotEnoughChildrenValidation("" + "['IfStmt',{}," + "['LiteralExpr',{'type':'boolean','value':true}]," + "['BlockStmt',{}]]", TagType.IfStmt, 3, 2); } public void testInvokeExprValidation() throws Exception { // correct statement testValidation("" + "['InvokeExpr',{'op':'.'}," + "['IdExpr',{'name':'x'}]," + "['LiteralExpr',{'type':'string','value':'foo'}]]"); // wrong number of children testNotEnoughChildrenValidation("" + "['InvokeExpr',{'op':'[]'}," + "['IdExpr',{'name':'x'}]]", TagType.InvokeExpr, 2, 1); // missing attribute testMissingArgument("" + "['InvokeExpr',{}," + "['IdExpr',{'name':'x'}]," + "['LiteralExpr',{'type':'string','value':'foo'}]]", TagAttr.OP, TagType.InvokeExpr); } public void testJmpStmtValidation() throws Exception { // correct statement testValidation("" + "['BreakStmt',{}]"); testValidation("" + "['BreakStmt',{'label':'s'}]"); testValidation("" + "['ContinueStmt',{}]"); testValidation("" + "['ContinueStmt',{'label':'s'}]"); // wrong number of children testTooManyChildrenValidation("" + "['BreakStmt',{}," + "['IdExpr',{'name':'s'}]]", TagType.BreakStmt, 0, 1); testTooManyChildrenValidation("" + "['ContinueStmt',{}," + "['IdExpr',{'name':'s'}]]", TagType.ContinueStmt, 0, 1); } public void testLabelledStmtValidation() throws Exception { // correct statement testValidation("" + "['LabelledStmt',{'label':'s'}," + "['IdExpr',{'name':'x'}]]"); // wrong number of children testNotEnoughChildrenValidation("" + "['LabelledStmt',{'label':'s'}]", TagType.LabelledStmt, 1, 0); testTooManyChildrenValidation("" + "['LabelledStmt',{'label':'s'}," + "['IdExpr',{'name':'x'}]," + "['IdExpr',{'name':'y'}]]", TagType.LabelledStmt, 1, 2); // missing attribute testMissingArgument("" + "['LabelledStmt',{}," + "['IdExpr',{'name':'x'}]]", TagAttr.LABEL, TagType.LabelledStmt); } public void testLiteralExprValidation() throws Exception { // correct statement testValidation("" + "['LiteralExpr',{'type':'string','value':'x'}]"); testValidation("" + "['LiteralExpr',{'type':'boolean','value':'true'}]"); testValidation("" + "['LiteralExpr',{'type':'number','value':'1.0'}]"); // wrong number of children testTooManyChildrenValidation("" + "['LiteralExpr',{'type':'number','value':'1.0'}," + "['BlockStmt',{}]]", TagType.LiteralExpr, 0, 1); // missing attribute testMissingArgument("" + "['LiteralExpr',{'type':'string'}]", TagAttr.VALUE, TagType.LiteralExpr); testMissingArgument("" + "['LiteralExpr',{'value':'1.0'}]", TagAttr.TYPE, TagType.LiteralExpr); } public void testLogicalExprValidation() throws Exception { // correct statement testValidation("" + "['LogicalAndExpr',{}," + "['IdExpr',{'name':'a'}]," + "['IdExpr',{'name':'b'}]]"); testValidation("" + "['LogicalOrExpr',{}," + "['IdExpr',{'name':'a'}]," + "['IdExpr',{'name':'b'}]]"); // wrong number of children testTooManyChildrenValidation("" + "['LogicalAndExpr',{}," + "['IdExpr',{'name':'a'}]," + "['IdExpr',{'name':'b'}]," + "['IdExpr',{'name':'c'}]]", TagType.LogicalAndExpr, 2, 3); testNotEnoughChildrenValidation("" + "['LogicalAndExpr',{}," + "['IdExpr',{'name':'a'}]]", TagType.LogicalAndExpr, 2, 1); } public void testNewExprValidation() throws Exception { // correct statement testValidation("" + "['NewExpr',{}," + "['IdExpr',{'name':'A'}]," + "['IdExpr',{'name':'x'}]]"); // wrong number of children testNotEnoughChildrenValidation("" + "['NewExpr',{}]", TagType.NewExpr, 1, 0); } public void testObjectExprValidation() throws Exception { // correct statement testValidation("" + "['ObjectExpr',{}]"); testValidation("" + "['ObjectExpr',{}," + "['DataProp',{'name':'x'}," + "['LiteralExpr',{'type':'number','value':1}]]," + "['DataProp',{'name':'y'}," + "['LiteralExpr',{'type':'number','value':2}]]]"); // wrong types of children TagType[] tags = {TagType.DataProp, TagType.GetterProp, TagType.SetterProp }; testWrongChildTypeValidation("" + "['ObjectExpr',{}," + "['DataProp',{'name':'x'}," + "['LiteralExpr',{'type':'number','value':1}]]," + "['IdExpr',{'name':'y'}]]", TagType.ObjectExpr, tags, TagType.IdExpr, 1); } public void testParamDeclValidation() throws Exception { // correct statement testValidation("" + "['ParamDecl',{}]"); testValidation("" + "['ParamDecl',{}," + "['IdPatt',{'name':'x'}]," + "['IdPatt',{'name':'y'}]]"); // wrong types of children testWrongChildTypeValidation("" + "['ParamDecl',{}," + "['IdPatt',{'name':'x'}]," + "['IdExpr',{'name':'y'}]]", TagType.ParamDecl, TagType.IdPatt, TagType.IdExpr, 1); } public void testRegExpExprValidation() throws Exception { // correct statement testValidation("" + "['RegExpExpr',{'body':'abc','flags':''}]"); testValidation("" + "['RegExpExpr',{'body':'abc','flags':'g'}]"); // wrong number of children testTooManyChildrenValidation("" + "['RegExpExpr',{'body':'abc','flags':'g'}," + "['IdExpr',{'name':'a'}]]", TagType.RegExpExpr, 0, 1); // missing attribute testMissingArgument("" + "['RegExpExpr',{'body':'abc'}]", TagAttr.FLAGS, TagType.RegExpExpr); testMissingArgument("" + "['RegExpExpr',{'flags':'g'}]", TagAttr.BODY, TagType.RegExpExpr); } public void testReturnStmtValidation() throws Exception { // correct statement testValidation("" + "['ReturnStmt',{}]"); testValidation("" + "['ReturnStmt',{}," + "['LiteralExpr',{'type':'number','value':1}]]"); // wrong number of children testTooManyChildrenValidation("" + "['ReturnStmt',{}," + "['IdExpr',{'name':'a'}]," + "['IdExpr',{'name':'b'}]]", TagType.ReturnStmt, 1, 2); } public void testSwitchStmtValidation() throws Exception { // correct statement testValidation("" + "['SwitchStmt',{}," + "['IdExpr',{'name':'x'}]," + "['Case',{}," + "['LiteralExpr',{'type':'number','value':1}]," + "['CallExpr',{}," + "['IdExpr',{'name':'foo'}]]]," + "['DefaultCase',{}," + "['CallExpr',{}," + "['IdExpr',{'name':'bar'}]]]]"); testValidation("" + "['SwitchStmt',{}," + "['IdExpr',{'name':'x'}]]"); // wrong number of children testNotEnoughChildrenValidation("" + "['SwitchStmt',{}]", TagType.SwitchStmt, 1, 0); // wrong types of children testWrongChildTypeValidation("" + "['SwitchStmt',{}," + "['IdExpr',{'name':'x'}]," + "['AssignExpr',{'op': '='}," + "['LiteralExpr',{'type':'number','value':1}]," + "['CallExpr',{}," + "['IdExpr',{'name':'foo'}]]]," + "['DefaultCase',{}," + "['CallExpr',{}," + "['IdExpr',{'name':'bar'}]]]]", TagType.SwitchStmt, new TagType[] { TagType.Case, TagType.DefaultCase }, TagType.AssignExpr, 1); testWrongChildTypeValidation("" + "['SwitchStmt',{}," + "['IdExpr',{'name':'x'}]," + "['DefaultCase',{}," + "['CallExpr',{}," + "['IdExpr',{'name':'foo'}]]]," + "['DefaultCase',{}," + "['CallExpr',{}," + "['IdExpr',{'name':'bar'}]]]]", TagType.SwitchStmt, TagType.Case, TagType.DefaultCase, 2); } public void testThisExprValidation() throws Exception { // correct statement testValidation("" + "['ThisExpr',{}]"); // wrong number of children testTooManyChildrenValidation("" + "['ThisExpr',{}," + "['IdExpr',{'name':'a'}]]", TagType.ThisExpr, 0, 1); } public void testThrowStmtValidation() throws Exception { // correct statement testValidation("" + "['ThrowStmt',{}," + "['IdExpr',{'name':'e'}]]"); // wrong number of children testTooManyChildrenValidation("" + "['ThrowStmt',{}," + "['IdExpr',{'name':'a'}]," + "['IdExpr',{'name':'b'}]]", TagType.ThrowStmt, 1, 2); } public void testTryStmtValidation() throws Exception { // correct statement testValidation("" + "['TryStmt',{}," + "['BlockStmt',{}]," + "['CatchClause',{}," + "['IdPatt',{'name':'e'}]," + "['BlockStmt',{}]]]"); testValidation("" + "['TryStmt',{}," + "['BlockStmt',{}]," + "['CatchClause',{}," + "['IdPatt',{'name':'e'}]," + "['BlockStmt',{}]]," + "['BlockStmt',{}]]"); // wrong number of children testNotEnoughChildrenValidation("" + "['TryStmt',{}," + "['CatchClause',{}," + "['IdPatt',{'name':'e'}]," + "['BlockStmt',{}]]]", TagType.TryStmt, 2, 1); testTooManyChildrenValidation("" + "['TryStmt',{}," + "['BlockStmt',{}]," + "['CatchClause',{}," + "['IdPatt',{'name':'e'}]," + "['BlockStmt',{}]]," + "['BlockStmt',{}]," + "['BlockStmt',{}]]", TagType.TryStmt, 3, 4); // wrong type of children testWrongChildTypeValidation("" + "['TryStmt',{}," + "['BlockStmt',{}]," + "['BlockStmt',{}," + "['IdPatt',{'name':'e'}]," + "['BlockStmt',{}]]," + "['BlockStmt',{}]]", TagType.TryStmt, new TagType[] { TagType.CatchClause, TagType.Empty }, TagType.BlockStmt, 1); testWrongChildTypeValidation("" + "['TryStmt',{}," + "['BlockStmt',{}]," + "['CatchClause',{}," + "['IdPatt',{'name':'e'}]," + "['BlockStmt',{}]]," + "['IdExpr',{'name': 'x'}]]", TagType.TryStmt, TagType.BlockStmt, TagType.IdExpr, 2); } public void testUnaryExprValidation() throws Exception { // correct statement testValidation("" + "['UnaryExpr',{'op':'-'}," + "['IdExpr',{'name':'x'}]]"); testValidation("" + "['UnaryExpr',{'op':'!'}," + "['CallExpr',{}," + "['IdExpr',{'name':'f'}]," + "['IdExpr',{'name':'x'}]]]"); // wrong number of children testNotEnoughChildrenValidation("" + "['UnaryExpr',{'op':'-'}]", TagType.UnaryExpr, 1, 0); testTooManyChildrenValidation("" + "['UnaryExpr',{'op':'+'}," + "['IdExpr',{'name':'x'}]," + "['IdExpr',{'name':'y'}]]", TagType.UnaryExpr, 1, 2); // missing attribute testMissingArgument("" + "['UnaryExpr',{}," + "['IdExpr',{'name':'x'}]]", TagAttr.OP, TagType.UnaryExpr); } public void testVarDeclValidation() throws Exception { // correct statement testValidation("" + "['VarDecl',{}," + "['IdPatt',{'name':'x'}]]"); testValidation("" + "['VarDecl',{}," + "['InitPatt',{}," + "['IdPatt',{'name':'x'}]," + "['LiteralExpr',{'type':'number','value':0}]]]"); testValidation("" + "['VarDecl',{}," + "['InitPatt',{}," + "['IdPatt',{'name':'x'}]," + "['LiteralExpr',{'type':'number','value':0}]]," + "['IdPatt',{'name':'y'}]]"); // wrong number of children testNotEnoughChildrenValidation("" + "['VarDecl',{}]", TagType.VarDecl, 1, 0); // wrong type of children testWrongChildTypeValidation("" + "['VarDecl',{}," + "['InitPatt',{}," + "['IdPatt',{'name':'x'}]," + "['LiteralExpr',{'type':'number','value':0}]]," + "['IdExpr',{'name':'y'}]," + "['IdPatt',{'name':'z'}]]", TagType.VarDecl, new TagType[] { TagType.InitPatt, TagType.IdPatt }, TagType.IdExpr, 1); } public void testWhileStmtValidation() throws Exception { // correct statement testValidation("" + "['WhileStmt',{}," + "['LiteralExpr',{'type':'boolean','value':true}]," + "['BlockStmt',{}]]"); testValidation("" + "['WhileStmt',{}," + "['LiteralExpr',{'type':'boolean','value':true}]," + "['IdExpr',{'name':'x'}]]"); // wrong number of children testNotEnoughChildrenValidation("" + "['WhileStmt',{}," + "['BlockStmt',{}]]", TagType.WhileStmt, 2, 1); testTooManyChildrenValidation("" + "['WhileStmt',{}," + "['LiteralExpr',{'type':'boolean','value':true}]," + "['IdExpr',{'name':'x'}]," + "['IdExpr',{'name':'y'}]]", TagType.WhileStmt, 2, 3); } public void testWithStmtValidation() throws Exception { // correct statement testValidation("" + "['WithStmt',{}," + "['IdExpr',{'name':'x'}]," + "['BlockStmt',{}]]"); // wrong number of children testNotEnoughChildrenValidation("" + "['WithStmt',{}," + "['BlockStmt',{}]]", TagType.WithStmt, 2, 1); testTooManyChildrenValidation("" + "['WithStmt',{}," + "['IdExpr',{'name':'A'}]," + "['IdExpr',{'name':'x'}]," + "['IdExpr',{'name':'y'}]]", TagType.WithStmt, 2, 3); } }