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