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