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