1 /*
   2  * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  */
  23 
  24 package dom.ls;
  25 
  26 import java.io.IOException;
  27 import java.io.StringBufferInputStream;
  28 
  29 import javax.xml.parsers.DocumentBuilder;
  30 import javax.xml.parsers.DocumentBuilderFactory;
  31 import javax.xml.parsers.ParserConfigurationException;
  32 
  33 import org.testng.Assert;
  34 import org.testng.annotations.Listeners;
  35 import org.testng.annotations.Test;
  36 import org.w3c.dom.Attr;
  37 import org.w3c.dom.DOMImplementation;
  38 import org.w3c.dom.Document;
  39 import org.w3c.dom.Element;
  40 import org.w3c.dom.NamedNodeMap;
  41 import org.w3c.dom.Node;
  42 import org.w3c.dom.NodeList;
  43 import org.w3c.dom.ls.DOMImplementationLS;
  44 import org.w3c.dom.ls.LSInput;
  45 import org.w3c.dom.ls.LSParser;
  46 import org.w3c.dom.ls.LSParserFilter;
  47 import org.w3c.dom.traversal.NodeFilter;
  48 import org.xml.sax.SAXException;
  49 
  50 /*
  51  * @test
  52  * @library /javax/xml/jaxp/libs /javax/xml/jaxp/unittest
  53  * @run testng/othervm -DrunSecMngr=true dom.ls.LSParserTCKTest
  54  * @run testng/othervm dom.ls.LSParserTCKTest
  55  * @summary Test Specifications and Descriptions for LSParser.
  56  */
  57 @Listeners({jaxp.library.BasePolicy.class})
  58 public class LSParserTCKTest {
  59 
  60     DOMImplementationLS implLS = null;
  61     public String xml1 = "<?xml version=\"1.0\"?><ROOT><ELEMENT1><CHILD1/><CHILD1><COC1/></CHILD1></ELEMENT1><ELEMENT2>test1<CHILD2/></ELEMENT2></ROOT>";
  62 
  63     /**
  64      * Equivalence class partitioning
  65      * with state, input and output values orientation
  66      * for public Document parse(LSInput is),
  67      * <br><b>pre-conditions</b>: set filter that REJECTs any CHILD* node,
  68      * <br><b>is</b>: xml1
  69      * <br><b>output</b>: XML document with ELEMNENT1 and ELEMENT2 only.
  70      */
  71     @Test
  72     public void testfilter0001() {
  73         LSParser parser = createLSParser();
  74         if (parser == null) {
  75             Assert.fail("Unable to create LSParser!");
  76         }
  77         // set filter
  78         parser.setFilter(new LSParserFilter() {
  79             public short startElement(Element elt) {
  80                 return FILTER_ACCEPT;
  81             }
  82 
  83             public short acceptNode(Node enode) {
  84                 if (enode.getNodeName().startsWith("CHILD")) {
  85                     return FILTER_REJECT;
  86                 }
  87                 return FILTER_ACCEPT;
  88             }
  89 
  90             public int getWhatToShow() {
  91                 return NodeFilter.SHOW_ALL;
  92             }
  93         });
  94         String expected = "<?xml version=\"1.0\"?><ROOT><ELEMENT1></ELEMENT1><ELEMENT2>test1</ELEMENT2></ROOT>";
  95         Document doc = parser.parse(getXmlSource(xml1));
  96         if (!match(expected, doc)) {
  97             Assert.fail("DOM structure after parsing is not equal to a structure of XML document, that being parsed");
  98         }
  99 
 100         System.out.println("OKAY");
 101     }
 102 
 103     public LSParserTCKTest(String name) {
 104         init();
 105     }
 106 
 107     protected void init() {
 108         Document doc = null;
 109         DocumentBuilder parser = null;
 110         try {
 111             parser = DocumentBuilderFactory.newInstance().newDocumentBuilder();
 112         } catch (ParserConfigurationException e) {
 113             e.printStackTrace();
 114         }
 115         StringBufferInputStream is = new StringBufferInputStream(xml1);
 116         try {
 117             doc = parser.parse(is);
 118         } catch (SAXException e) {
 119             e.printStackTrace();
 120         } catch (IOException e) {
 121             e.printStackTrace();
 122         }
 123         DOMImplementation impl = doc.getImplementation();
 124         implLS = (DOMImplementationLS) impl.getFeature("LS", "3.0");
 125     }
 126 
 127     public LSInput getXmlSource(String xmldoc) {
 128         LSInput srcdoc = createLSInput();
 129         srcdoc.setStringData(xmldoc);
 130         return srcdoc;
 131     }
 132 
 133     public LSInput createLSInput() {
 134         return implLS.createLSInput();
 135     }
 136 
 137     public LSParser createLSParser() {
 138         return implLS.createLSParser(DOMImplementationLS.MODE_SYNCHRONOUS, "http://www.w3.org/2001/XMLSchema");
 139     }
 140 
 141     public boolean match(String template, Node source) {
 142         LSParser dp = createLSParser();
 143         if (dp == null) {
 144             System.out.println("Can not create LSParser.");
 145             return false;
 146         }
 147         LSInput src = getXmlSource(template);
 148         Document doc = dp.parse(src);
 149         return checkXMLs(doc, source);
 150     }
 151 
 152     // ========================== XML comparison code ==============
 153     public boolean checkXMLs(Node template, Node source) {
 154         if (source == null || template == null) {
 155             return template == source;
 156         }
 157         String tname = template.getLocalName();
 158         String tvalue = template.getNodeValue();
 159         NamedNodeMap tattr = template.getAttributes();
 160         NodeList tchildren = template.getChildNodes();
 161 
 162         String sname = source.getLocalName();
 163         String svalue = source.getNodeValue();
 164         NamedNodeMap sattr = source.getAttributes();
 165         NodeList schildren = source.getChildNodes();
 166         if (tname != null && !tname.equals(sname)) {
 167             return false;
 168         }
 169         if (tvalue != null && !tvalue.equals(svalue)) {
 170             return false;
 171         }
 172         if (tattr != null && sattr != null) {
 173             if (sattr.getLength() != tattr.getLength()) {
 174                 return false;
 175             }
 176             for (int i = 0; i < tattr.getLength(); i++) {
 177                 Attr t = (Attr) tattr.item(i);
 178                 Attr s = (Attr) sattr.getNamedItem(t.getName());
 179                 if (!checkXMLAttrs(t, s)) {
 180                     // ref.println(sname+": [expected attr: " + t +
 181                     // "; actual attr: " +s+"]");
 182                     return false;
 183                 }
 184             }
 185         } else if (tattr != null || sattr != null) {
 186             return false;
 187         }
 188 
 189         for (int i = 0; i < tchildren.getLength(); i++) {
 190             if (!checkXMLs(tchildren.item(i), schildren.item(i))) {
 191                 // ref.println(sname+": [expected node: "+tchildren.item(i)
 192                 // +"; actual node: "+schildren.item(i)+"]");
 193                 return false;
 194             }
 195         }
 196         return true;
 197     }
 198 
 199     public boolean checkXMLAttrs(Attr template, Attr source) {
 200         if (source == null || template == null) {
 201             return template == source;
 202         }
 203         String tname = template.getName();
 204         String tvalue = template.getValue();
 205         String sname = source.getName();
 206         String svalue = source.getValue();
 207         System.out.println("Attr:" + tname + "?" + sname);
 208         if (tname != null && !tname.equals(sname)) {
 209             // ref.println("Attr Name:" + tname + "!=" + sname);
 210             return false;
 211         }
 212         if (tvalue != null && !tvalue.equals(svalue)) {
 213             // ref.println("Attr value:" + tvalue + "!=" + svalue);
 214             return false;
 215         }
 216         // ref.println("Attr:" + tname + ":" + tvalue + "=" + sname + ":" +
 217         // svalue);
 218         return true;
 219     }
 220 
 221     /**
 222      * Equivalence class partitioning with state, input and output values
 223      * orientation for public Document parse(LSInput is), <br>
 224      * <b>pre-conditions</b>: set filter that SKIPs ELEMENT1 node, <br>
 225      * <b>is</b>: xml1 <br>
 226      * <b>output</b>: XML document with CHILD1 and ELEMENT2 only.
 227      */
 228     @Test
 229     public void testFilter0002() {
 230         LSParser parser = createLSParser();
 231         if (parser == null) {
 232             Assert.fail("Unable to create LSParser!");
 233         }
 234         // set filter
 235         parser.setFilter(new LSParserFilter() {
 236             public short startElement(Element elt) {
 237                 return FILTER_ACCEPT;
 238             }
 239 
 240             public short acceptNode(Node enode) {
 241                 if (enode.getNodeName().startsWith("ELEMENT1")) {
 242                     return FILTER_SKIP;
 243                 }
 244                 return FILTER_ACCEPT;
 245             }
 246 
 247             public int getWhatToShow() {
 248                 return NodeFilter.SHOW_ALL;
 249             }
 250         });
 251         String expected = "<?xml version=\"1.0\"?><ROOT><CHILD1/><CHILD1><COC1/></CHILD1><ELEMENT2>test1<CHILD2/></ELEMENT2></ROOT>";
 252         Document doc = parser.parse(getXmlSource(xml1));
 253         if (!match(expected, doc)) {
 254             Assert.fail("DOM structure after parsing is not equal to a structure of XML document, that being parsed");
 255         }
 256         System.out.println("OKAY");
 257     }
 258 
 259     /**
 260      * Equivalence class partitioning with state, input and output values
 261      * orientation for public Document parse(LSInput is), <br>
 262      * <b>pre-conditions</b>: set filter that SKIPs ELEMENT1 node, <br>
 263      * <b>is</b>: xml1 <br>
 264      * <b>output</b>: XML document with ELEMENT1 only.
 265      */
 266     @Test
 267     public void testFilter0003() {
 268         LSParser parser = createLSParser();
 269         if (parser == null) {
 270             Assert.fail("Unable to create LSParser!");
 271         }
 272         // set filter
 273         parser.setFilter(new LSParserFilter() {
 274             public short startElement(Element elt) {
 275                 return FILTER_ACCEPT;
 276             }
 277 
 278             public short acceptNode(Node enode) {
 279                 if (enode.getNodeName().startsWith("ELEMENT2")) {
 280                     return FILTER_INTERRUPT;
 281                 }
 282                 return FILTER_ACCEPT;
 283             }
 284 
 285             public int getWhatToShow() {
 286                 return NodeFilter.SHOW_ALL;
 287             }
 288         });
 289         String expected = "<ROOT><ELEMENT1><CHILD1/><CHILD1><COC1/></CHILD1></ELEMENT1></ROOT>";
 290         Document doc = parser.parse(getXmlSource(xml1));
 291         if (!match(expected, doc)) {
 292             Assert.fail("DOM structure after parsing is not equal to a structure of XML document, that being parsed");
 293         }
 294         System.out.println("OKAY");
 295     }
 296 
 297     /**
 298      * Equivalence class partitioning with state, input and output values
 299      * orientation for public Document parse(LSInput is), <br>
 300      * <b>pre-conditions</b>: set filter that accepts all, <br>
 301      * <b>is</b>: xml1 <br>
 302      * <b>output</b>: full XML document.
 303      */
 304     @Test
 305     public void testFilter0004() {
 306         LSParser parser = createLSParser();
 307         if (parser == null) {
 308             Assert.fail("Unable to create LSParser!");
 309         }
 310         // set filter
 311         parser.setFilter(new LSParserFilter() {
 312             public short startElement(Element elt) {
 313                 return FILTER_ACCEPT;
 314             }
 315 
 316             public short acceptNode(Node enode) {
 317                 return FILTER_ACCEPT;
 318             }
 319 
 320             public int getWhatToShow() {
 321                 return NodeFilter.SHOW_ALL;
 322             }
 323         });
 324         String expected = "<ROOT><ELEMENT1><CHILD1/><CHILD1><COC1/></CHILD1></ELEMENT1><ELEMENT2>test1<CHILD2/></ELEMENT2></ROOT>";
 325         Document doc = parser.parse(getXmlSource(xml1));
 326         if (!match(expected, doc)) {
 327             Assert.fail("DOM structure after parsing is not equal to a structure of XML document, that being parsed");
 328         }
 329         System.out.println("OKAY");
 330     }
 331 
 332     /**
 333      * Equivalence class partitioning with state, input and output values
 334      * orientation for public Document parse(LSInput is), <br>
 335      * <b>pre-conditions</b>: set filter that REJECTs all, <br>
 336      * <b>is</b>: xml1 <br>
 337      * <b>output</b>: empty XML document.
 338      */
 339     @Test
 340     public void testFilter0005() {
 341         LSParser parser = createLSParser();
 342         if (parser == null) {
 343             Assert.fail("Unable to create LSParser!");
 344         }
 345         // set filter
 346         parser.setFilter(new LSParserFilter() {
 347             public short startElement(Element elt) {
 348                 return FILTER_ACCEPT;
 349             }
 350 
 351             public short acceptNode(Node enode) {
 352                 return FILTER_REJECT;
 353             }
 354 
 355             public int getWhatToShow() {
 356                 return NodeFilter.SHOW_ALL;
 357             }
 358         });
 359         Document doc = parser.parse(getXmlSource(xml1));
 360         NodeList children = doc.getDocumentElement().getChildNodes();
 361         if (children.getLength() != 0) {
 362             Assert.fail("Not all children skipped");
 363         }
 364         System.out.println("OKAY");
 365     }
 366 
 367     /**
 368      * Equivalence class partitioning with state, input and output values
 369      * orientation for public Document parse(LSInput is), <br>
 370      * <b>pre-conditions</b>: set filter that SKIPs all, <br>
 371      * <b>is</b>: xml1 <br>
 372      * <b>output</b>: empty XML document.
 373      */
 374     @Test
 375     public void testFilter0006() {
 376         LSParser parser = createLSParser();
 377         if (parser == null) {
 378             Assert.fail("Unable to create LSParser!");
 379         }
 380         // set filter
 381         parser.setFilter(new LSParserFilter() {
 382             public short startElement(Element elt) {
 383                 return FILTER_ACCEPT;
 384             }
 385 
 386             public short acceptNode(Node enode) {
 387                 return FILTER_SKIP;
 388             }
 389 
 390             public int getWhatToShow() {
 391                 return NodeFilter.SHOW_ALL;
 392             }
 393         });
 394         Document doc = parser.parse(getXmlSource(xml1));
 395         NodeList children = doc.getDocumentElement().getChildNodes();
 396         if (children.getLength() != 0) {
 397             Assert.fail("Not all children skipped");
 398         }
 399         System.out.println("OKAY");
 400     }
 401 
 402     /**
 403      * Equivalence class partitioning with state, input and output values
 404      * orientation for public Document parse(LSInput is), <br>
 405      * <b>pre-conditions</b>: set filter that REJECTs any CHILD* start element, <br>
 406      * <b>is</b>: xml1 <br>
 407      * <b>output</b>: XML document with ELEMENT1 and ELEMENT2 only.
 408      */
 409     @Test
 410     public void testFilter0007() {
 411         LSParser parser = createLSParser();
 412         if (parser == null) {
 413             Assert.fail("Unable to create LSParser!");
 414         }
 415         // set filter
 416         parser.setFilter(new LSParserFilter() {
 417             public short startElement(Element elt) {
 418                 if (elt.getTagName().startsWith("CHILD")) {
 419                     return FILTER_REJECT;
 420                 }
 421                 return FILTER_ACCEPT;
 422             }
 423 
 424             public short acceptNode(Node enode) {
 425                 return FILTER_ACCEPT;
 426             }
 427 
 428             public int getWhatToShow() {
 429                 return NodeFilter.SHOW_ALL;
 430             }
 431         });
 432         String expected = "<?xml version=\"1.0\"?><ROOT><ELEMENT1></ELEMENT1><ELEMENT2>test1</ELEMENT2></ROOT>";
 433         Document doc = parser.parse(getXmlSource(xml1));
 434         if (!match(expected, doc)) {
 435             Assert.fail("DOM structure after parsing is not equal to a structure of XML document, that being parsed");
 436         }
 437         System.out.println("OKAY");
 438     }
 439 
 440     /**
 441      * Equivalence class partitioning with state, input and output values
 442      * orientation for public Document parse(LSInput is), <br>
 443      * <b>pre-conditions</b>: set filter that SKIPs ELEMENT1 start element, <br>
 444      * <b>is</b>: xml1 <br>
 445      * <b>output</b>: XML document with CHILD1 and ELEMENT2 only.
 446      */
 447     @Test
 448     public void testFilter0008() {
 449         LSParser parser = createLSParser();
 450         if (parser == null) {
 451             Assert.fail("Unable to create LSParser!");
 452         }
 453         // set filter
 454         parser.setFilter(new LSParserFilter() {
 455             public short startElement(Element elt) {
 456                 if (elt.getTagName().equals("ELEMENT1")) {
 457                     return FILTER_SKIP;
 458                 }
 459                 return FILTER_ACCEPT;
 460             }
 461 
 462             public short acceptNode(Node enode) {
 463                 return FILTER_ACCEPT;
 464             }
 465 
 466             public int getWhatToShow() {
 467                 return NodeFilter.SHOW_ALL;
 468             }
 469         });
 470         String expected = "<?xml version=\"1.0\"?><ROOT><CHILD1/><CHILD1><COC1/></CHILD1><ELEMENT2>test1<CHILD2/></ELEMENT2></ROOT>";
 471         Document doc = parser.parse(getXmlSource(xml1));
 472         if (!match(expected, doc)) {
 473             Assert.fail("DOM structure after parsing is not equal to a structure of XML document, that being parsed");
 474         }
 475         System.out.println("OKAY");
 476     }
 477 
 478     /**
 479      * Equivalence class partitioning with state, input and output values
 480      * orientation for public Document parse(LSInput is), <br>
 481      * <b>pre-conditions</b>: set filter that SKIPs ELEMENT1 start element, <br>
 482      * <b>is</b>: xml1 <br>
 483      * <b>output</b>: XML document with ELEMENT1 only.
 484      */
 485     @Test
 486     public void testFilter0009() {
 487         LSParser parser = createLSParser();
 488         if (parser == null) {
 489             Assert.fail("Unable to create LSParser!");
 490         }
 491         // set filter
 492         parser.setFilter(new LSParserFilter() {
 493             public short startElement(Element elt) {
 494                 if (elt.getTagName().startsWith("ELEMENT2")) {
 495                     return FILTER_INTERRUPT;
 496                 }
 497                 return FILTER_ACCEPT;
 498             }
 499 
 500             public short acceptNode(Node enode) {
 501                 return FILTER_ACCEPT;
 502             }
 503 
 504             public int getWhatToShow() {
 505                 return NodeFilter.SHOW_ALL;
 506             }
 507         });
 508         String expected = "<ROOT><ELEMENT1><CHILD1/><CHILD1><COC1/></CHILD1></ELEMENT1></ROOT>";
 509         Document doc = parser.parse(getXmlSource(xml1));
 510         if (!match(expected, doc)) {
 511             Assert.fail("DOM structure after parsing is not equal to a structure of XML document, that being parsed");
 512         }
 513         System.out.println("OKAY");
 514     }
 515 
 516     /**
 517      * Equivalence class partitioning with state, input and output values
 518      * orientation for public Document parse(LSInput is), <br>
 519      * <b>pre-conditions</b>: set filter that REJECTs all start element, <br>
 520      * <b>is</b>: xml1 <br>
 521      * <b>output</b>: empty XML document.
 522      */
 523     @Test
 524     public void testFilter0010() {
 525         LSParser parser = createLSParser();
 526         if (parser == null) {
 527             Assert.fail("Unable to create LSParser");
 528         }
 529         // set filter
 530         parser.setFilter(new LSParserFilter() {
 531             public short startElement(Element elt) {
 532                 return FILTER_REJECT;
 533             }
 534 
 535             public short acceptNode(Node enode) {
 536                 return FILTER_ACCEPT;
 537             }
 538 
 539             public int getWhatToShow() {
 540                 return NodeFilter.SHOW_ALL;
 541             }
 542         });
 543         Document doc = parser.parse(getXmlSource(xml1));
 544         NodeList children = doc.getDocumentElement().getChildNodes();
 545         if (children.getLength() != 0) {
 546             Assert.fail("Not all children skipped");
 547         }
 548         System.out.println("OKAY");
 549     }
 550 
 551     /**
 552      * Equivalence class partitioning with state, input and output values
 553      * orientation for public Document parse(LSInput is), <br>
 554      * <b>pre-conditions</b>: set filter that SKIPs all, <br>
 555      * <b>is</b>: xml1 <br>
 556      * <b>output</b>: empty XML document.
 557      */
 558     @Test
 559     public void testFilter0011() {
 560         LSParser parser = createLSParser();
 561         if (parser == null) {
 562             Assert.fail("Unable to create LSParser");
 563         }
 564         // set filter
 565         parser.setFilter(new LSParserFilter() {
 566             public short startElement(Element elt) {
 567                 return FILTER_SKIP;
 568             }
 569 
 570             public short acceptNode(Node enode) {
 571                 return FILTER_ACCEPT;
 572             }
 573 
 574             public int getWhatToShow() {
 575                 return NodeFilter.SHOW_ALL;
 576             }
 577         });
 578         Document doc = parser.parse(getXmlSource(xml1));
 579         NodeList children = doc.getDocumentElement().getChildNodes();
 580         if (children.getLength() != 1) {
 581             Assert.fail("Not all Element nodes skipped");
 582         }
 583         System.out.println("OKAY");
 584     }
 585 
 586 }
 587