/* * Copyright 2008 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.template.soy.soytree; import static com.google.template.soy.soytree.TemplateSubject.assertThatTemplateContent; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotSame; import static org.junit.Assert.assertSame; import static org.junit.Assert.assertTrue; import com.google.common.collect.ImmutableList; import com.google.template.soy.base.SourceLocation; import com.google.template.soy.error.ExplodingErrorReporter; import com.google.template.soy.exprparse.SoyParsingContext; import com.google.template.soy.soytree.SoyNode.StandaloneNode; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; /** * Unit tests for MsgNode. * */ @RunWith(JUnit4.class) public class MsgNodeTest { private static final SourceLocation X = SourceLocation.UNKNOWN; private static final SoyParsingContext FAIL = SoyParsingContext.exploding(); @Test public void testGenPlaceholderNames() throws Exception { // Test message structure: // {msg desc=""} // <a href="{$url1}"> [START_LINK_1] // {$boo}{$foo.goo}{1 + 1}{2 + 2} [BOO, GOO_1, XXX_1, XXX_2] // </a> [END_LINK] // <br><br/><br /><br /><br> [START_BREAK, BREAK_1, BREAK_2, BREAK_2, START_BREAK] // <a href="{$url2}"> [START_LINK_2] // {$boo}{$goo}{$goo2}{2 + 2} [BOO, GOO_3, GOO_2, XXX_2] // </a> [END_LINK] // <br phname="zoo"> [ZOO_1] // <br phname="zoo"> [ZOO_1] // {$zoo phname="zoo"} [ZOO_2] // {$zoo} [ZOO_3] // {$foo.zoo phname="zoo"} [ZOO_4] // {$foo.zoo phname="zoo"} [ZOO_4] // {call .helper phname="zoo" /} [ZOO_5] // {call .helper phname="zoo" /} [ZOO_6] // {/msg} // // Note: The three 'print' tags {$foo.goo}, {$goo}, and {$goo2} end up as placeholders GOO_1, // GOO_3, and GOO_2 due to the following steps. // 1. {$foo.goo} and {$goo} have base placeholder name GOO, while {$goo2} has GOO_2. // 2. To differentiate {$foo.goo} and {$goo}, normally the new names would be GOO_1 and GOO_2. // 3. However, since GOO_2 is already used for {$goo2}, we use GOO_1 and GOO_3 instead. MsgNode msg = MsgNode.msg(0, "desc=\"\"", X).build(FAIL); // Link 1 start tag. MsgHtmlTagNode link1Start = new MsgHtmlTagNode.Builder( 1, ImmutableList.<StandaloneNode>of( new RawTextNode(0, "<a href=\"", X), new PrintNode.Builder(0, true /* isImplicit */, X) .exprText("$url1") .build(FAIL), new RawTextNode(0, "\">", X)), X) .build(ExplodingErrorReporter.get()); msg.addChild(new MsgPlaceholderNode(0, link1Start)); // Link 1 contents. msg.addChild( new MsgPlaceholderNode( 0, new PrintNode.Builder(0, true /* isImplicit */, X).exprText("$boo").build(FAIL))); msg.addChild( new MsgPlaceholderNode( 0, new PrintNode.Builder(0, true /* isImplicit */, X).exprText("$foo.goo").build(FAIL))); msg.addChild( new MsgPlaceholderNode( 0, new PrintNode.Builder(0, true /* isImplicit */, X).exprText("1 + 1").build(FAIL))); msg.addChild( new MsgPlaceholderNode( 0, new PrintNode.Builder(0, true /* isImplicit */, X).exprText("2 + 2").build(FAIL))); // Link 1 end tag. msg.addChild(new MsgPlaceholderNode(0, createSimpleHtmlTag("</a>"))); // Intervening 'br' tags. msg.addChild(new MsgPlaceholderNode(0, createSimpleHtmlTag("<br>"))); msg.addChild(new MsgPlaceholderNode(0, createSimpleHtmlTag("<br/>"))); msg.addChild(new MsgPlaceholderNode(0, createSimpleHtmlTag("<br />"))); msg.addChild(new MsgPlaceholderNode(0, createSimpleHtmlTag("<br />"))); msg.addChild(new MsgPlaceholderNode(0, createSimpleHtmlTag("<br>"))); // Link 2 start tag. MsgHtmlTagNode link2Start = new MsgHtmlTagNode.Builder( 2, ImmutableList.<StandaloneNode>of( new RawTextNode(0, "<a href=\"", X), new PrintNode.Builder(0, true /* isImplicit */, X) .exprText("$url2") .build(FAIL), new RawTextNode(0, "\">", X)), X) .build(ExplodingErrorReporter.get()); msg.addChild(new MsgPlaceholderNode(0, link2Start)); // Link 2 contents. msg.addChild( new MsgPlaceholderNode( 0, new PrintNode.Builder(0, true /* isImplicit */, X).exprText("$boo").build(FAIL))); msg.addChild( new MsgPlaceholderNode( 0, new PrintNode.Builder(0, true /* isImplicit */, X).exprText("$goo").build(FAIL))); msg.addChild( new MsgPlaceholderNode( 0, new PrintNode.Builder(0, true /* isImplicit */, X).exprText("$goo2").build(FAIL))); msg.addChild( new MsgPlaceholderNode( 0, new PrintNode.Builder(0, true /* isImplicit */, X).exprText("2 + 2").build(FAIL))); // Link 2 end tag. msg.addChild(new MsgPlaceholderNode(0, createSimpleHtmlTag("</a>"))); // All the parts with base placeholder name ZOO. msg.addChild(new MsgPlaceholderNode(0, createSimpleHtmlTag("<br phname=\"zoo\">"))); msg.addChild(new MsgPlaceholderNode(0, createSimpleHtmlTag("<br phname=\"zoo\">"))); msg.addChild( new MsgPlaceholderNode( 0, new PrintNode.Builder(0, true /* isImplicit */, X) .exprText("$zoo") .userSuppliedPlaceholderName("zoo") .build(FAIL))); msg.addChild( new MsgPlaceholderNode( 0, new PrintNode.Builder(0, true /* isImplicit */, X).exprText("$zoo").build(FAIL))); msg.addChild( new MsgPlaceholderNode( 0, new PrintNode.Builder(0, true /* isImplicit */, X) .exprText("$foo.zoo") .userSuppliedPlaceholderName("zoo") .build(FAIL))); msg.addChild( new MsgPlaceholderNode( 0, new PrintNode.Builder(0, true /* isImplicit */, X) .exprText("$foo.zoo") .userSuppliedPlaceholderName("zoo") .build(FAIL))); msg.addChild( new MsgPlaceholderNode( 0, new CallBasicNode.Builder(3, X) .commandText(".helper") .userSuppliedPlaceholderName("zoo") .build(FAIL))); msg.addChild( new MsgPlaceholderNode( 0, new CallBasicNode.Builder(4, X) .commandText(".helper") .userSuppliedPlaceholderName("zoo") .build(FAIL))); assertEquals("START_LINK_1", msg.getPlaceholderName((MsgPlaceholderNode) msg.getChild(0))); assertEquals("BOO", msg.getPlaceholderName((MsgPlaceholderNode) msg.getChild(1))); assertEquals("GOO_1", msg.getPlaceholderName((MsgPlaceholderNode) msg.getChild(2))); assertEquals("XXX_1", msg.getPlaceholderName((MsgPlaceholderNode) msg.getChild(3))); assertEquals("XXX_2", msg.getPlaceholderName((MsgPlaceholderNode) msg.getChild(4))); assertEquals("END_LINK", msg.getPlaceholderName((MsgPlaceholderNode) msg.getChild(5))); assertEquals("START_BREAK", msg.getPlaceholderName((MsgPlaceholderNode) msg.getChild(6))); assertEquals("BREAK_1", msg.getPlaceholderName((MsgPlaceholderNode) msg.getChild(7))); assertEquals("BREAK_2", msg.getPlaceholderName((MsgPlaceholderNode) msg.getChild(8))); assertEquals("BREAK_2", msg.getPlaceholderName((MsgPlaceholderNode) msg.getChild(9))); assertEquals("START_BREAK", msg.getPlaceholderName((MsgPlaceholderNode) msg.getChild(10))); assertEquals("START_LINK_2", msg.getPlaceholderName((MsgPlaceholderNode) msg.getChild(11))); assertEquals("BOO", msg.getPlaceholderName((MsgPlaceholderNode) msg.getChild(12))); assertEquals("GOO_3", msg.getPlaceholderName((MsgPlaceholderNode) msg.getChild(13))); assertEquals("GOO_2", msg.getPlaceholderName((MsgPlaceholderNode) msg.getChild(14))); assertEquals("XXX_2", msg.getPlaceholderName((MsgPlaceholderNode) msg.getChild(15))); assertEquals("END_LINK", msg.getPlaceholderName((MsgPlaceholderNode) msg.getChild(16))); assertEquals("ZOO_1", msg.getPlaceholderName((MsgPlaceholderNode) msg.getChild(17))); assertEquals("ZOO_1", msg.getPlaceholderName((MsgPlaceholderNode) msg.getChild(18))); assertEquals("ZOO_2", msg.getPlaceholderName((MsgPlaceholderNode) msg.getChild(19))); assertEquals("ZOO_3", msg.getPlaceholderName((MsgPlaceholderNode) msg.getChild(20))); assertEquals("ZOO_4", msg.getPlaceholderName((MsgPlaceholderNode) msg.getChild(21))); assertEquals("ZOO_4", msg.getPlaceholderName((MsgPlaceholderNode) msg.getChild(22))); assertEquals("ZOO_5", msg.getPlaceholderName((MsgPlaceholderNode) msg.getChild(23))); assertEquals("ZOO_6", msg.getPlaceholderName((MsgPlaceholderNode) msg.getChild(24))); assertSame(msg.getChild(0), msg.getRepPlaceholderNode("START_LINK_1")); assertSame(msg.getChild(1), msg.getRepPlaceholderNode("BOO")); assertSame(msg.getChild(2), msg.getRepPlaceholderNode("GOO_1")); assertSame(msg.getChild(3), msg.getRepPlaceholderNode("XXX_1")); assertSame(msg.getChild(4), msg.getRepPlaceholderNode("XXX_2")); assertSame(msg.getChild(5), msg.getRepPlaceholderNode("END_LINK")); assertSame(msg.getChild(6), msg.getRepPlaceholderNode("START_BREAK")); assertSame(msg.getChild(7), msg.getRepPlaceholderNode("BREAK_1")); assertSame(msg.getChild(8), msg.getRepPlaceholderNode("BREAK_2")); assertNotSame(msg.getChild(9), msg.getRepPlaceholderNode("BREAK_2")); assertNotSame(msg.getChild(10), msg.getRepPlaceholderNode("START_BREAK")); assertSame(msg.getChild(11), msg.getRepPlaceholderNode("START_LINK_2")); assertNotSame(msg.getChild(12), msg.getRepPlaceholderNode("BOO")); assertSame(msg.getChild(13), msg.getRepPlaceholderNode("GOO_3")); assertSame(msg.getChild(14), msg.getRepPlaceholderNode("GOO_2")); assertNotSame(msg.getChild(15), msg.getRepPlaceholderNode("XXX_2")); assertNotSame(msg.getChild(16), msg.getRepPlaceholderNode("END_LINK")); assertSame(msg.getChild(17), msg.getRepPlaceholderNode("ZOO_1")); assertNotSame(msg.getChild(18), msg.getRepPlaceholderNode("ZOO_1")); assertSame(msg.getChild(19), msg.getRepPlaceholderNode("ZOO_2")); assertSame(msg.getChild(20), msg.getRepPlaceholderNode("ZOO_3")); assertSame(msg.getChild(21), msg.getRepPlaceholderNode("ZOO_4")); assertNotSame(msg.getChild(22), msg.getRepPlaceholderNode("ZOO_4")); assertSame(msg.getChild(23), msg.getRepPlaceholderNode("ZOO_5")); assertSame(msg.getChild(24), msg.getRepPlaceholderNode("ZOO_6")); } // ----------------------------------------------------------------------------------------------- // Plural/select messages. /** * Tests whether the names for plural and select nodes are assigned correctly. This contains a * normal select variable and three fall back plural variables with conflict. */ @Test public void testGenPlrselVarNames1() { /* Tests the soy message in the following code: {msg desc=""} {select $gender} // Normal select variable. GENDER. {case 'female'} {plural $values.people[0]} // Plural variable, fall back to NUM_1 {case 1}{$person} added one person to her circle. {default}{$person} added many people to her circle. {/plural} {case 'male'} {plural $values.people[1]} // Plural variable, fall back to NUM_2 {case 1}{$person} added one person to his circle. {default}{$person} added many people to his circle. {/plural} {default} {plural $values.people[1]} // Plural variable, fall back to NUM_2 {case 1}{$person} added one person to his/her circle. {default}{$person} added many people to his/her circle. {/plural} {/select} {/msg} */ // Build the message. MsgNode msg = MsgNode.msg(0, "desc=\"\"", X).build(FAIL); MsgSelectNode selectNode = new MsgSelectNode.Builder(0, "$gender", X).build(FAIL); // case 'female' MsgSelectCaseNode femaleNode = new MsgSelectCaseNode(0, X, "female"); MsgPluralNode pluralNode1 = new MsgPluralNode.Builder(0, "$values.people[0] offset=\"1\"", X).build(FAIL); MsgPluralCaseNode pluralCaseNode11 = new MsgPluralCaseNode(0, X, 1); MsgPlaceholderNode placeholderNode111 = new MsgPlaceholderNode( 0, new PrintNode.Builder(0, false /* isImplicit */, X).exprText("$person").build(FAIL)); pluralCaseNode11.addChild(placeholderNode111); RawTextNode rawTextNode111 = new RawTextNode(0, " added one person to her circle.", X); pluralCaseNode11.addChild(rawTextNode111); pluralNode1.addChild(pluralCaseNode11); MsgPluralDefaultNode pluralDefaultNode12 = new MsgPluralDefaultNode(0, X); MsgPlaceholderNode placeholderNode121 = new MsgPlaceholderNode( 0, new PrintNode.Builder(0, false /* isImplicit */, X).exprText("$person").build(FAIL)); pluralDefaultNode12.addChild(placeholderNode121); RawTextNode rawTextNode121 = new RawTextNode(0, " added many people to her circle.", X); pluralDefaultNode12.addChild(rawTextNode121); pluralNode1.addChild(pluralCaseNode11); femaleNode.addChild(pluralNode1); selectNode.addChild(femaleNode); // case 'male' MsgSelectCaseNode maleNode = new MsgSelectCaseNode(0, X, "male"); MsgPluralNode pluralNode2 = new MsgPluralNode.Builder(0, "$values.people[1]", X).build(FAIL); MsgPluralCaseNode pluralCaseNode21 = new MsgPluralCaseNode(0, X, 1); MsgPlaceholderNode placeholderNode211 = new MsgPlaceholderNode( 0, new PrintNode.Builder(0, false /* isImplicit */, X).exprText("$person").build(FAIL)); pluralCaseNode21.addChild(placeholderNode211); RawTextNode rawTextNode211 = new RawTextNode(0, " added one person to his circle.", X); pluralCaseNode21.addChild(rawTextNode211); pluralNode2.addChild(pluralCaseNode21); MsgPluralDefaultNode pluralDefaultNode22 = new MsgPluralDefaultNode(0, X); MsgPlaceholderNode placeholderNode221 = new MsgPlaceholderNode( 0, new PrintNode.Builder(0, false /* isImplicit */, X).exprText("$person").build(FAIL)); pluralDefaultNode22.addChild(placeholderNode221); RawTextNode rawTextNode221 = new RawTextNode(0, " added many people to his circle.", X); pluralDefaultNode22.addChild(rawTextNode221); pluralNode2.addChild(pluralDefaultNode22); maleNode.addChild(pluralNode2); selectNode.addChild(maleNode); // default MsgSelectDefaultNode selectDefaultNode = new MsgSelectDefaultNode(0, X); MsgPluralNode pluralNode3 = new MsgPluralNode.Builder(0, "$values.people[1]", X).build(FAIL); MsgPluralCaseNode pluralCaseNode31 = new MsgPluralCaseNode(0, X, 1); MsgPlaceholderNode placeholderNode311 = new MsgPlaceholderNode( 0, new PrintNode.Builder(0, false /* isImplicit */, X).exprText("$person").build(FAIL)); pluralCaseNode31.addChild(placeholderNode311); RawTextNode rawTextNode311 = new RawTextNode(0, " added one person to his/her circle.", X); pluralCaseNode31.addChild(rawTextNode311); pluralNode3.addChild(pluralCaseNode31); MsgPluralDefaultNode pluralDefaultNode32 = new MsgPluralDefaultNode(0, X); MsgPlaceholderNode placeholderNode321 = new MsgPlaceholderNode( 0, new PrintNode.Builder(0, false /* isImplicit */, X).exprText("$person").build(FAIL)); pluralDefaultNode32.addChild(placeholderNode321); RawTextNode rawTextNode321 = new RawTextNode(0, " added many people to his/her circle.", X); pluralDefaultNode32.addChild(rawTextNode321); pluralNode3.addChild(pluralDefaultNode32); selectDefaultNode.addChild(pluralNode3); selectNode.addChild(selectDefaultNode); msg.addChild(selectNode); // msg.printMessageNode(); // Test. MsgSelectNode nodeSelect = (MsgSelectNode) msg.getChild(0); assertEquals("GENDER", msg.getSelectVarName(nodeSelect)); assertSame(nodeSelect, msg.getRepSelectNode("GENDER")); MsgPluralNode nodePlural1 = (MsgPluralNode) nodeSelect.getChild(0).getChild(0); assertEquals("NUM_1", msg.getPluralVarName(nodePlural1)); MsgPluralNode nodePlural2 = (MsgPluralNode) nodeSelect.getChild(1).getChild(0); assertEquals("NUM_2", msg.getPluralVarName(nodePlural2)); MsgPluralNode nodePlural3 = (MsgPluralNode) nodeSelect.getChild(2).getChild(0); assertEquals("NUM_2", msg.getPluralVarName(nodePlural3)); assertNotSame(nodePlural2, nodePlural3); MsgPluralNode repPluralNode1 = msg.getRepPluralNode("NUM_1"); assertSame(repPluralNode1, nodePlural1); MsgPluralNode repPluralNode2 = msg.getRepPluralNode("NUM_2"); assertSame(repPluralNode2, nodePlural2); assertNotSame(repPluralNode2, nodePlural3); } /** Tests whether the names for plural and select nodes are assigned correctly. */ @Test public void testGenPlrselVarNames2() { /* Tests the soy message in the following code: {msg desc=""} {select $gender[5]} // Select variable, fall back to STATUS. {case 'female'} {plural $woman.num_friends} // Plural variable, NUM_FRIENDS_1 {case 1}{$person} added one person to her circle. {default}{$person} added many people to her circle. {/plural} {case 'male'} {plural $man.num_friends} // Plural variable, NUM_FRIENDS_2 {case 1}{$person} added one person to his circle. {default}{$person} added many people to his circle. {/plural} {default} {plural $thing.nEntities} // Plural variable, N_ENTITIES {case 1}{$object} added one entity to its circle. {default}{$object} added many entities to its circle. {/plural} {/select} {/msg} */ // Build the message. MsgNode msg = MsgNode.msg(0, "desc=\"\"", X).build(FAIL); MsgSelectNode selectNode = new MsgSelectNode.Builder(0, "$gender[5]", X).build(FAIL); // case 'female' MsgSelectCaseNode femaleNode = new MsgSelectCaseNode(0, X, "female"); MsgPluralNode pluralNode1 = new MsgPluralNode.Builder(0, "$woman.num_friends", X).build(FAIL); MsgPluralCaseNode pluralCaseNode11 = new MsgPluralCaseNode(0, X, 1); MsgPlaceholderNode placeholderNode111 = new MsgPlaceholderNode( 0, new PrintNode.Builder(0, false /* isImplicit */, X).exprText("$person").build(FAIL)); pluralCaseNode11.addChild(placeholderNode111); RawTextNode rawTextNode111 = new RawTextNode(0, " added one person to her circle.", X); pluralCaseNode11.addChild(rawTextNode111); pluralNode1.addChild(pluralCaseNode11); MsgPluralDefaultNode pluralDefaultNode12 = new MsgPluralDefaultNode(0, X); MsgPlaceholderNode placeholderNode121 = new MsgPlaceholderNode( 0, new PrintNode.Builder(0, false /* isImplicit */, X).exprText("$person").build(FAIL)); pluralDefaultNode12.addChild(placeholderNode121); RawTextNode rawTextNode121 = new RawTextNode(0, " added many people to her circle.", X); pluralDefaultNode12.addChild(rawTextNode121); pluralNode1.addChild(pluralCaseNode11); femaleNode.addChild(pluralNode1); selectNode.addChild(femaleNode); // case 'male' MsgSelectCaseNode maleNode = new MsgSelectCaseNode(0, X, "male"); MsgPluralNode pluralNode2 = new MsgPluralNode.Builder(0, "$man.num_friends", X).build(FAIL); MsgPluralCaseNode pluralCaseNode21 = new MsgPluralCaseNode(0, X, 1); MsgPlaceholderNode placeholderNode211 = new MsgPlaceholderNode( 0, new PrintNode.Builder(0, false /* isImplicit */, X).exprText("$person").build(FAIL)); pluralCaseNode21.addChild(placeholderNode211); RawTextNode rawTextNode211 = new RawTextNode(0, " added one person to his circle.", X); pluralCaseNode21.addChild(rawTextNode211); pluralNode2.addChild(pluralCaseNode21); MsgPluralDefaultNode pluralDefaultNode22 = new MsgPluralDefaultNode(0, X); MsgPlaceholderNode placeholderNode221 = new MsgPlaceholderNode( 0, new PrintNode.Builder(0, false /* isImplicit */, X).exprText("$person").build(FAIL)); pluralDefaultNode22.addChild(placeholderNode221); RawTextNode rawTextNode221 = new RawTextNode(0, " added many people to his circle.", X); pluralDefaultNode22.addChild(rawTextNode221); pluralNode2.addChild(pluralDefaultNode22); maleNode.addChild(pluralNode2); selectNode.addChild(maleNode); // case 'other' MsgSelectDefaultNode selectDefaultNode = new MsgSelectDefaultNode(0, X); MsgPluralNode pluralNode3 = new MsgPluralNode.Builder(0, "$thing.nEntities", X).build(FAIL); MsgPluralCaseNode pluralCaseNode31 = new MsgPluralCaseNode(0, X, 1); MsgPlaceholderNode placeholderNode311 = new MsgPlaceholderNode( 0, new PrintNode.Builder(0, false /* isImplicit */, X).exprText("$person").build(FAIL)); pluralCaseNode31.addChild(placeholderNode311); RawTextNode rawTextNode311 = new RawTextNode(0, " added one person to his/her circle.", X); pluralCaseNode31.addChild(rawTextNode311); pluralNode3.addChild(pluralCaseNode31); MsgPluralDefaultNode pluralDefaultNode32 = new MsgPluralDefaultNode(0, X); MsgPlaceholderNode placeholderNode321 = new MsgPlaceholderNode( 0, new PrintNode.Builder(0, false /* isImplicit */, X).exprText("$person").build(FAIL)); pluralDefaultNode32.addChild(placeholderNode321); RawTextNode rawTextNode321 = new RawTextNode(0, " added many people to his/her circle.", X); pluralDefaultNode32.addChild(rawTextNode321); pluralNode3.addChild(pluralDefaultNode32); selectDefaultNode.addChild(pluralNode3); selectNode.addChild(selectDefaultNode); msg.addChild(selectNode); // Test. MsgSelectNode nodeSelect = (MsgSelectNode) msg.getChild(0); assertEquals("STATUS", msg.getSelectVarName(nodeSelect)); assertSame(nodeSelect, msg.getRepSelectNode("STATUS")); MsgPluralNode nodePlural1 = (MsgPluralNode) nodeSelect.getChild(0).getChild(0); assertEquals("NUM_FRIENDS_1", msg.getPluralVarName(nodePlural1)); MsgPluralNode nodePlural2 = (MsgPluralNode) nodeSelect.getChild(1).getChild(0); assertEquals("NUM_FRIENDS_2", msg.getPluralVarName(nodePlural2)); MsgPluralNode nodePlural3 = (MsgPluralNode) nodeSelect.getChild(2).getChild(0); assertEquals("N_ENTITIES", msg.getPluralVarName(nodePlural3)); assertNotSame(nodePlural2, nodePlural3); MsgPluralNode repPluralNode1 = msg.getRepPluralNode("NUM_FRIENDS_1"); assertSame(repPluralNode1, nodePlural1); MsgPluralNode repPluralNode2 = msg.getRepPluralNode("NUM_FRIENDS_2"); assertSame(repPluralNode2, nodePlural2); MsgPluralNode repPluralNode3 = msg.getRepPluralNode("N_ENTITIES"); assertSame(repPluralNode3, nodePlural3); } @Test public void testGenPlrselVarNames3() { /* Tests the soy message in the following code: {msg desc=""} {select $gender.person} // Select variable, fall back to PERSON_1. {case 'female'} {plural $woman.num_friends.person} // Plural variable, PERSON_3. {case 1}{$person} added one person to her circle. // PERSON_5. {default}{$person2} added many people to her circle. // PERSON_2. {/plural} {case default} {plural $man.num_friends.person} // Plural variable, PERSON_4. {case 1}{$person} added one person to his circle. // PERSON_5. {default}{$person2} added many people to his circle. // PERSON_2. {/plural} {/select} {/msg} */ // Build the message. MsgNode msg = MsgNode.msg(0, "desc=\"\"", X).build(FAIL); MsgSelectNode selectNode = new MsgSelectNode.Builder(0, "$gender.person", X).build(FAIL); // case 'female' MsgSelectCaseNode femaleNode = new MsgSelectCaseNode(0, X, "female"); MsgPluralNode pluralNode1 = new MsgPluralNode.Builder(0, "$woman.num_friends.person", X).build(FAIL); MsgPluralCaseNode pluralCaseNode11 = new MsgPluralCaseNode(0, X, 1); MsgPlaceholderNode placeholderNode111 = new MsgPlaceholderNode( 0, new PrintNode.Builder(0, false /* isImplicit */, X).exprText("$person").build(FAIL)); pluralCaseNode11.addChild(placeholderNode111); RawTextNode rawTextNode111 = new RawTextNode(0, " added one person to her circle.", X); pluralCaseNode11.addChild(rawTextNode111); pluralNode1.addChild(pluralCaseNode11); MsgPluralDefaultNode pluralDefaultNode12 = new MsgPluralDefaultNode(0, X); MsgPlaceholderNode placeholderNode121 = new MsgPlaceholderNode( 0, new PrintNode.Builder(0, false /* isImplicit */, X).exprText("$person2").build(FAIL)); pluralDefaultNode12.addChild(placeholderNode121); RawTextNode rawTextNode121 = new RawTextNode(0, " added many people to her circle.", X); pluralDefaultNode12.addChild(rawTextNode121); pluralNode1.addChild(pluralDefaultNode12); femaleNode.addChild(pluralNode1); selectNode.addChild(femaleNode); // case 'other' MsgSelectDefaultNode selectDefaultNode = new MsgSelectDefaultNode(0, X); MsgPluralNode pluralNode3 = new MsgPluralNode.Builder(0, "$man.num_friends.person", X).build(FAIL); MsgPluralCaseNode pluralCaseNode31 = new MsgPluralCaseNode(0, X, 1); MsgPlaceholderNode placeholderNode311 = new MsgPlaceholderNode( 0, new PrintNode.Builder(0, false /* isImplicit */, X).exprText("$person").build(FAIL)); pluralCaseNode31.addChild(placeholderNode311); RawTextNode rawTextNode311 = new RawTextNode(0, " added one person to his/her circle.", X); pluralCaseNode31.addChild(rawTextNode311); pluralNode3.addChild(pluralCaseNode31); MsgPluralDefaultNode pluralDefaultNode32 = new MsgPluralDefaultNode(0, X); MsgPlaceholderNode placeholderNode321 = new MsgPlaceholderNode( 0, new PrintNode.Builder(0, false /* isImplicit */, X).exprText("$person2").build(FAIL)); pluralDefaultNode32.addChild(placeholderNode321); RawTextNode rawTextNode321 = new RawTextNode(0, " added many people to his/her circle.", X); pluralDefaultNode32.addChild(rawTextNode321); pluralNode3.addChild(pluralDefaultNode32); selectDefaultNode.addChild(pluralNode3); selectNode.addChild(selectDefaultNode); msg.addChild(selectNode); // Test. MsgSelectNode nodeSelect = (MsgSelectNode) msg.getChild(0); assertEquals("PERSON_1", msg.getSelectVarName(nodeSelect)); assertSame(nodeSelect, msg.getRepSelectNode("PERSON_1")); MsgPluralNode nodePlural1 = (MsgPluralNode) nodeSelect.getChild(0).getChild(0); assertEquals("PERSON_3", msg.getPluralVarName(nodePlural1)); MsgPlaceholderNode phNode11 = (MsgPlaceholderNode) nodePlural1.getChild(0).getChild(0); assertEquals("PERSON_5", msg.getPlaceholderName(phNode11)); MsgPlaceholderNode phNode12 = (MsgPlaceholderNode) nodePlural1.getChild(1).getChild(0); assertEquals("PERSON_2", msg.getPlaceholderName(phNode12)); MsgPluralNode nodePlural2 = (MsgPluralNode) nodeSelect.getChild(1).getChild(0); assertEquals("PERSON_4", msg.getPluralVarName(nodePlural2)); MsgPlaceholderNode phNode21 = (MsgPlaceholderNode) nodePlural2.getChild(0).getChild(0); assertEquals("PERSON_5", msg.getPlaceholderName(phNode21)); MsgPlaceholderNode phNode22 = (MsgPlaceholderNode) nodePlural2.getChild(1).getChild(0); assertEquals("PERSON_2", msg.getPlaceholderName(phNode22)); MsgPlaceholderNode repPhNode1 = msg.getRepPlaceholderNode("PERSON_5"); assertSame(repPhNode1, phNode11); MsgPlaceholderNode repPhNode2 = msg.getRepPlaceholderNode("PERSON_2"); assertSame(repPhNode2, phNode12); MsgSelectNode repSelectNode = msg.getRepSelectNode("PERSON_1"); assertSame(repSelectNode, nodeSelect); MsgPluralNode repPluralNode1 = msg.getRepPluralNode("PERSON_3"); assertSame(repPluralNode1, nodePlural1); MsgPluralNode repPluralNode2 = msg.getRepPluralNode("PERSON_4"); assertSame(repPluralNode2, nodePlural2); } /** Tests arbitrary expression as plural variable. */ @Test public void testGenPlrselVarNames4() { /* Tests the soy message in the following code: {msg desc=""} {select $gender} // Select variable, fall back to GENDER. {case 'female'} {plural $woman.num} // Plural variable, NUM_1 {case 1}{$person} added one person to her circle. {default}{$person} added many people to her circle. {/plural} {case 'male'} {plural $man.num} // Plural variable, NUM_2 {case 1}{$person} added one person to his circle. {default}{$person} added many people to his circle. {/plural} {default} {plural {max($woman.num_friends, $man.num_friends)}} // Plural variable, NUM_3 {case 1}{$object} added one person to his/her circle. {default}{$object} added many people to his/her circle. {/plural} {/select} {/msg} */ // Build the message. MsgNode msg = MsgNode.msg(0, "desc=\"\"", X).build(FAIL); MsgSelectNode selectNode = new MsgSelectNode.Builder(0, "$gender", X).build(FAIL); // case 'female' MsgSelectCaseNode femaleNode = new MsgSelectCaseNode(0, X, "female"); MsgPluralNode pluralNode1 = new MsgPluralNode.Builder(0, "$woman.num", X).build(FAIL); MsgPluralCaseNode pluralCaseNode11 = new MsgPluralCaseNode(0, X, 1); MsgPlaceholderNode placeholderNode111 = new MsgPlaceholderNode( 0, new PrintNode.Builder(0, false /* isImplicit */, X).exprText("$person").build(FAIL)); pluralCaseNode11.addChild(placeholderNode111); RawTextNode rawTextNode111 = new RawTextNode(0, " added one person to her circle.", X); pluralCaseNode11.addChild(rawTextNode111); pluralNode1.addChild(pluralCaseNode11); MsgPluralDefaultNode pluralDefaultNode12 = new MsgPluralDefaultNode(0, X); MsgPlaceholderNode placeholderNode121 = new MsgPlaceholderNode( 0, new PrintNode.Builder(0, false /* isImplicit */, X).exprText("$person").build(FAIL)); pluralDefaultNode12.addChild(placeholderNode121); RawTextNode rawTextNode121 = new RawTextNode(0, " added many people to her circle.", X); pluralDefaultNode12.addChild(rawTextNode121); pluralNode1.addChild(pluralCaseNode11); femaleNode.addChild(pluralNode1); selectNode.addChild(femaleNode); // case 'male' MsgSelectCaseNode maleNode = new MsgSelectCaseNode(0, X, "male"); MsgPluralNode pluralNode2 = new MsgPluralNode.Builder(0, "$man.num", X).build(FAIL); MsgPluralCaseNode pluralCaseNode21 = new MsgPluralCaseNode(0, X, 1); MsgPlaceholderNode placeholderNode211 = new MsgPlaceholderNode( 0, new PrintNode.Builder(0, false /* isImplicit */, X).exprText("$person").build(FAIL)); pluralCaseNode21.addChild(placeholderNode211); RawTextNode rawTextNode211 = new RawTextNode(0, " added one person to his circle.", X); pluralCaseNode21.addChild(rawTextNode211); pluralNode2.addChild(pluralCaseNode21); MsgPluralDefaultNode pluralDefaultNode22 = new MsgPluralDefaultNode(0, X); MsgPlaceholderNode placeholderNode221 = new MsgPlaceholderNode( 0, new PrintNode.Builder(0, false /* isImplicit */, X).exprText("$person").build(FAIL)); pluralDefaultNode22.addChild(placeholderNode221); RawTextNode rawTextNode221 = new RawTextNode(0, " added many people to his circle.", X); pluralDefaultNode22.addChild(rawTextNode221); pluralNode2.addChild(pluralDefaultNode22); maleNode.addChild(pluralNode2); selectNode.addChild(maleNode); // case 'other' MsgSelectDefaultNode selectDefaultNode = new MsgSelectDefaultNode(0, X); MsgPluralNode pluralNode3 = new MsgPluralNode.Builder(0, "max($woman.num, $man.num)", X).build(FAIL); MsgPluralCaseNode pluralCaseNode31 = new MsgPluralCaseNode(0, X, 1); MsgPlaceholderNode placeholderNode311 = new MsgPlaceholderNode( 0, new PrintNode.Builder(0, false /* isImplicit */, X).exprText("$person").build(FAIL)); pluralCaseNode31.addChild(placeholderNode311); RawTextNode rawTextNode311 = new RawTextNode(0, " added one person to his/her circle.", X); pluralCaseNode31.addChild(rawTextNode311); pluralNode3.addChild(pluralCaseNode31); MsgPluralDefaultNode pluralDefaultNode32 = new MsgPluralDefaultNode(0, X); MsgPlaceholderNode placeholderNode321 = new MsgPlaceholderNode( 0, new PrintNode.Builder(0, false /* isImplicit */, X).exprText("$person").build(FAIL)); pluralDefaultNode32.addChild(placeholderNode321); RawTextNode rawTextNode321 = new RawTextNode(0, " added many people to his/her circle.", X); pluralDefaultNode32.addChild(rawTextNode321); pluralNode3.addChild(pluralDefaultNode32); selectDefaultNode.addChild(pluralNode3); selectNode.addChild(selectDefaultNode); msg.addChild(selectNode); // Test. MsgSelectNode nodeSelect = (MsgSelectNode) msg.getChild(0); assertEquals("GENDER", msg.getSelectVarName(nodeSelect)); assertSame(nodeSelect, msg.getRepSelectNode("GENDER")); MsgPluralNode nodePlural1 = (MsgPluralNode) nodeSelect.getChild(0).getChild(0); assertEquals("NUM_1", msg.getPluralVarName(nodePlural1)); MsgPluralNode nodePlural2 = (MsgPluralNode) nodeSelect.getChild(1).getChild(0); assertEquals("NUM_2", msg.getPluralVarName(nodePlural2)); MsgPluralNode nodePlural3 = (MsgPluralNode) nodeSelect.getChild(2).getChild(0); assertEquals("NUM_3", msg.getPluralVarName(nodePlural3)); assertNotSame(nodePlural2, nodePlural3); MsgPluralNode repPluralNode1 = msg.getRepPluralNode("NUM_1"); assertSame(repPluralNode1, nodePlural1); MsgPluralNode repPluralNode2 = msg.getRepPluralNode("NUM_2"); assertSame(repPluralNode2, nodePlural2); MsgPluralNode repPluralNode3 = msg.getRepPluralNode("NUM_3"); assertSame(repPluralNode3, nodePlural3); } @Test public void testIsSelectMsg() { /* Tests the soy message in the following code: {msg desc=""} {select $gender.person} // Select variable, fall back to PERSON_1. {case 'female'} 'female' {case default} 'default' {/select} {/msg} */ // Build the message. MsgNode msg = MsgNode.msg(0, "desc=\"\"", X).build(FAIL); MsgSelectNode selectNode = new MsgSelectNode.Builder(0, "$gender.person", X).build(FAIL); // case 'female' MsgSelectCaseNode femaleNode = new MsgSelectCaseNode(0, X, "female"); RawTextNode femaleTextNode = new RawTextNode(0, "female", X); femaleNode.addChild(femaleTextNode); selectNode.addChild(femaleNode); // case 'other' MsgSelectDefaultNode selectDefaultNode = new MsgSelectDefaultNode(0, X); RawTextNode defaultTextNode = new RawTextNode(0, "default", X); selectDefaultNode.addChild(defaultTextNode); selectNode.addChild(selectDefaultNode); msg.addChild(selectNode); // Test. assertTrue(msg.isSelectMsg()); assertTrue(msg.isPlrselMsg()); } @Test public void testIsPluralMsg() { /* Tests the soy message in the following code: {msg desc=""} {plural $woman.num} // Plural variable, NUM_1 {case 1}{$person} added one person to her circle. {default}{$person} added many people to her circle. {/plural} {/msg} */ // Build the message. MsgNode msg = MsgNode.msg(0, "desc=\"\"", X).build(FAIL); MsgPluralNode pluralNode1 = new MsgPluralNode.Builder(0, "$woman.num", X).build(FAIL); MsgPluralCaseNode pluralCaseNode11 = new MsgPluralCaseNode(0, X, 1); MsgPlaceholderNode placeholderNode111 = new MsgPlaceholderNode( 0, new PrintNode.Builder(0, false /* isImplicit */, X).exprText("$person").build(FAIL)); pluralCaseNode11.addChild(placeholderNode111); RawTextNode rawTextNode111 = new RawTextNode(0, " added one person to her circle.", X); pluralCaseNode11.addChild(rawTextNode111); pluralNode1.addChild(pluralCaseNode11); MsgPluralDefaultNode pluralDefaultNode12 = new MsgPluralDefaultNode(0, X); MsgPlaceholderNode placeholderNode121 = new MsgPlaceholderNode( 0, new PrintNode.Builder(0, false /* isImplicit */, X).exprText("$person").build(FAIL)); pluralDefaultNode12.addChild(placeholderNode121); RawTextNode rawTextNode121 = new RawTextNode(0, " added many people to her circle.", X); pluralDefaultNode12.addChild(rawTextNode121); msg.addChild(pluralNode1); // Test. assertTrue(msg.isPluralMsg()); assertTrue(msg.isPlrselMsg()); } @Test public void testIsRawTextMsg() { /* Tests the soy message in the following code: {msg desc=""} "raw text" {/msg} */ // Build the message. MsgNode msg = MsgNode.msg(0, "desc=\"\"", X).build(FAIL); RawTextNode rawTextNode = new RawTextNode(0, "raw text", X); msg.addChild(rawTextNode); // Test. assertTrue(msg.isRawTextMsg()); assertTrue(!msg.isPlrselMsg()); } @Test public void testWrongNumberOfGenderExprs() { assertThatTemplateContent("{msg desc=\"\" genders=\"\"}{/msg}") .causesError(MsgNode.WRONG_NUMBER_OF_GENDER_EXPRS) .at(1, 1); assertThatTemplateContent("{msg desc=\"\" genders=\"$foo, $bar, $baz, $quux\"}{/msg}") .causesError(MsgNode.WRONG_NUMBER_OF_GENDER_EXPRS) .at(1, 1); } // ----------------------------------------------------------------------------------------------- // Helpers. private static MsgHtmlTagNode createSimpleHtmlTag(String content) { return new MsgHtmlTagNode.Builder( 0, ImmutableList.<StandaloneNode>of(new RawTextNode(0, content, X)), X) .build(ExplodingErrorReporter.get()); } }