View Javadoc
1   package org.apache.maven.shared.utils.xml.pull;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *  http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  
22  import java.io.IOException;
23  import java.io.StringReader;
24  import org.apache.maven.shared.utils.xml.Xpp3Dom;
25  import org.apache.maven.shared.utils.xml.Xpp3DomBuilder;
26  
27  import org.junit.Test;
28  
29  import static org.apache.maven.shared.utils.xml.Xpp3Dom.mergeXpp3Dom;
30  import static org.junit.Assert.*;
31  
32  /**
33   * @author Kristian Rosenvold
34   */
35  public class Xpp3DomTest
36  {
37  
38      private Xpp3Dom createElement( String element, String value )
39      {
40          Xpp3Dom t1s1 = new Xpp3Dom( element );
41          t1s1.setValue( value );
42          return t1s1;
43      }
44  
45  
46      @Test
47      public void mergePrecedenceSelfClosed()
48          throws XmlPullParserException, IOException
49      {
50          Xpp3Dom parentConfig = build( "<configuration><items><item/></items></configuration>" );
51          Xpp3Dom childConfig = build( "<configuration><items><item>ooopise</item></items></configuration>" );
52  
53          Xpp3Dom result = Xpp3Dom.mergeXpp3Dom( childConfig, parentConfig );
54          Xpp3Dom items = result.getChild( "items" );
55  
56          assertEquals( 1, items.getChildCount() );
57          Xpp3Dom item = items.getChild( 0 );
58          assertEquals( "ooopise", item.getValue() );
59      }
60  
61      @Test
62      public void mergePrecedenceOpenClose()
63          throws XmlPullParserException, IOException
64      {
65          Xpp3Dom parentConfig = build( "<configuration><items><item></item></items></configuration>" );
66          Xpp3Dom childConfig = build( "<configuration><items><item>ooopise</item></items></configuration>" );
67  
68          Xpp3Dom result = Xpp3Dom.mergeXpp3Dom( childConfig, parentConfig );
69          Xpp3Dom items = result.getChild( "items" );
70  
71          assertEquals( 1, items.getChildCount() );
72          Xpp3Dom item = items.getChild( 0 );
73          assertEquals( "ooopise", item.getValue() );
74      }
75  
76      @Test
77      public void selfOverrideOnRootNode()
78      {
79          // Todo: This does not work when loaded. Probably a bug related to null vs "" handling
80          //      Xpp3Dom t1 = build( "<top combine.self='override' attr='value'></top>" );
81  
82          Xpp3Dom t1 = new Xpp3Dom( "top" );
83          t1.setAttribute( "attr", "value" );
84  
85          t1.setAttribute( Xpp3Dom.SELF_COMBINATION_MODE_ATTRIBUTE, Xpp3Dom.SELF_COMBINATION_OVERRIDE );
86  
87          Xpp3Dom t2 = build( "<top attr2='value2'>val2</top>" );
88          Xpp3Dom result = mergeXpp3Dom( t1, t2 );
89  
90          assertEquals( 2, result.getAttributeNames().length );
91          assertNull( result.getValue() );
92      }
93  
94      @Test
95      public void mergeValuesOnRootNode()
96      {
97          Xpp3Dom t1 = build( "<root attr='value'/>" );
98          Xpp3Dom t2 = build( "<root attr2='value2'>t2Val</root>" );
99          Xpp3Dom result = mergeXpp3Dom( t1, t2 );
100         assertEquals( 2, result.getAttributeNames().length );
101         assertEquals( result.getValue(), t2.getValue() );
102     }
103 
104     @Test
105     public void mergeAttributesOnRootNode()
106     {
107         Xpp3Dom t1 = build( "<root combine.self='merge' attr='value'/>" );
108         Xpp3Dom t2 = build( "<root attr2='value2'/>" );
109 
110         Xpp3Dom dom = mergeXpp3Dom( t1, t2 );
111         assertEquals( 3, dom.getAttributeNames().length );
112     }
113 
114     @Test
115     public void combineAppend()
116     {
117         Xpp3Dom t1 = new Xpp3Dom( "root" );
118         t1.setAttribute( Xpp3Dom.CHILDREN_COMBINATION_MODE_ATTRIBUTE, Xpp3Dom.CHILDREN_COMBINATION_APPEND );
119         t1.addChild( createElement( "sub", "s1Value" ) );
120 
121         Xpp3Dom t2 = new Xpp3Dom( "root" );
122         t2.addChild( createElement( "sub", "s1Value" ) );
123 
124         Xpp3Dom result = mergeXpp3Dom( t1, t2 );
125 
126         assertEquals( 2, result.getChildren( "sub" ).length );
127     }
128 
129     @Test
130     public void mergeOverride()
131     {
132         Xpp3Dom t1 = new Xpp3Dom( "root" );
133         t1.setAttribute( Xpp3Dom.CHILDREN_COMBINATION_MODE_ATTRIBUTE, Xpp3Dom.CHILDREN_COMBINATION_APPEND );
134         t1.addChild( createElement( "sub", "s1Value" ) );
135 
136         Xpp3Dom t2 = new Xpp3Dom( "root" );
137         t2.addChild( createElement( "sub", "s1Value" ) );
138 
139         Xpp3Dom result = mergeXpp3Dom( t1, t2, Boolean.TRUE );
140 
141         assertEquals( 1, result.getChildren( "sub" ).length );
142     }
143 
144 
145     @Test( expected = NullPointerException.class )
146     public void nullValue()
147     {
148         //noinspection ConstantConditions
149         new Xpp3Dom( "top" ).setAttribute( null, "value" );
150     }
151 
152     @Test( expected = NullPointerException.class )
153     public void nullAttribute()
154     {
155         //noinspection ConstantConditions
156         new Xpp3Dom( "root" ).setAttribute( "attr", null );
157     }
158 
159 
160     @Test
161     public void testEquals()
162     {
163         Xpp3Dom dom = new Xpp3Dom( "single" );
164         dom.addChild( new Xpp3Dom( "kid" ) );
165 
166         Xpp3Dom other = new Xpp3Dom( "single" );
167         other.addChild( new Xpp3Dom( "kid2" ) );
168 
169         assertEquals( dom, dom );
170         //noinspection ObjectEqualsNull
171         assertFalse( dom.equals( null ) );
172         assertFalse( dom.equals( new Xpp3Dom( (String) null ) ) );
173         assertFalse( dom.equals( other ) );
174     }
175 
176     @Test
177     public void dominantWinsCollections()
178         throws XmlPullParserException
179     {
180         Xpp3Dom parent = build( "<root><entries><entry>uno</entry><entry>dos</entry></entries></root>" );
181         Xpp3Dom dominant = build( "<root><entries><entry>tres</entry></entries></root>" );
182 
183         Xpp3Dom result = mergeXpp3Dom( dominant, parent );
184 
185         Xpp3Dom items = result.getChild( "entries" );
186         assertEquals( 1, items.getChildCount() );
187 
188         assertElemEquals( "tres", items.getChild( 0 ) );
189     }
190 
191     @Test
192     public void combineChildrenAppendTest()
193         throws XmlPullParserException
194     {
195         Xpp3Dom parent =
196             build( "<root><entries><entry>uno</entry><entry>dos</entry><entry>tres</entry></entries></root>" );
197         Xpp3Dom child = build( "<root><entries combine.children=\"append\"><entry>quatro</entry></entries></root>" );
198 
199         Xpp3Dom result = mergeXpp3Dom( child, parent );
200 
201         Xpp3Dom items = result.getChild( "entries" );
202         assertEquals( 4, items.getChildCount() );
203 
204         Xpp3Dom[] item = items.getChildren();
205 
206         assertElemEquals( "uno", item[0] );
207         assertElemEquals( "dos", item[1] );
208         assertElemEquals( "tres", item[2] );
209         assertElemEquals( "quatro", item[3] );
210     }
211 
212     @Test
213     public void unchangedWithFirstOrLastEmpty()
214         throws Exception
215     {
216         String configStr = "<root><entries><entry/><entry>test</entry><entry/></entries></root>";
217         Xpp3Dom dominant = build( configStr );
218         Xpp3Dom duplicatedDominant = build( configStr );
219         validateEntries( dominant );
220         Xpp3Dom result = mergeXpp3Dom( dominant, duplicatedDominant );
221         validateEntries( result );
222     }
223 
224     private void validateEntries( Xpp3Dom result )
225     {
226         Xpp3Dom entries = result.getChild( "entries" );
227         assertEquals( 3, entries.getChildCount() );
228         assertXpp3Null( entries.getChild( 0 ) );
229         assertEquals( "test", entries.getChild( 1 ).getValue() );
230         assertXpp3Null( entries.getChild( 2 ) );
231     }
232 
233 
234     static void assertElemEquals( String value, Xpp3Dom element )
235     {
236         assertEquals( value, element.getValue() );
237     }
238 
239 
240     void assertXpp3Null( Xpp3Dom entry )
241     {
242         // Todo: When we used xpp3dom, all methods using this assert used to return null
243         assertEquals( "", entry.getValue() );
244     }
245 
246     @Test
247     public void recessiveChildrenIncludedWhenDominantEmpty()
248         throws Exception
249     {
250         String dominant = "<root><baz>bazzy</baz></root>";
251         String recessive = "<root><bar>barry</bar></root>";
252 
253         Xpp3Dom merged = mergeXpp3Dom( build( dominant ), build( recessive ) );
254 
255         assertEquals( 2, merged.getChildCount() );
256         assertEquals( "bazzy", merged.getChild( "baz" ).getValue() );
257         assertEquals( "barry", merged.getChild( "bar" ).getValue() );
258     }
259 
260     static Xpp3Dom build( String stringContent )
261     {
262         return Xpp3DomBuilder.build( new StringReader( stringContent ) );
263     }
264 
265     @Test
266     public void duplicatedChildren()
267         throws IOException, XmlPullParserException
268     {
269         String dupes = "<root><baz>x</baz><baz>y</baz></root>";
270         assertEquals( "y", build( dupes ).getChild( "baz" ).getValue() );
271     }
272 
273 }