github.com/matislovas/ratago@v0.0.0-20240408115641-cc0857415a7a/xslt/stylesheet_test.go (about)

     1  package xslt
     2  
     3  import (
     4  	"fmt"
     5  	"io/ioutil"
     6  	"os"
     7  	"path"
     8  	"testing"
     9  
    10  	"github.com/matislovas/gokogiri/xml"
    11  )
    12  
    13  // Simple naive test; primarily exists as a canary in case test helpers break
    14  func TestNaive(t *testing.T) {
    15  	xslFile := "testdata/test.xsl"
    16  	inputXml := "testdata/test.xml"
    17  	outputXml := "testdata/test.out"
    18  
    19  	runXslTest(t, xslFile, inputXml, outputXml)
    20  }
    21  
    22  // Helper where actual checking occurs
    23  func runXslTestWithOptions(t *testing.T, xslFile, inputXmlFile, outputXmlFile string, testOptions StylesheetOptions) bool {
    24  	style, _ := xml.ReadFile(xslFile, xml.StrictParseOption)
    25  	input, _ := xml.ReadFile(inputXmlFile, xml.StrictParseOption)
    26  	outData, _ := ioutil.ReadFile(outputXmlFile)
    27  	expected := string(outData)
    28  	stylesheet, _ := ParseStylesheet(style, xslFile)
    29  	output, _ := stylesheet.Process(input, testOptions)
    30  	if output != expected {
    31  		t.Error(xslFile, "failed")
    32  		fmt.Println("---- EXPECTED  ", xslFile, "----")
    33  		fmt.Println(expected)
    34  		fmt.Println("---- ACTUAL  ", xslFile, "----")
    35  		fmt.Println(output)
    36  		return false
    37  	}
    38  	return true
    39  }
    40  
    41  func runXslTest(t *testing.T, xslFile, inputXmlFile, outputXmlFile string) bool {
    42  	testOptions := StylesheetOptions{false, nil}
    43  	return runXslTestWithOptions(t, xslFile, inputXmlFile, outputXmlFile, testOptions)
    44  }
    45  
    46  // check whether a file exists
    47  func exists(path string) (bool, error) {
    48  	_, err := os.Stat(path)
    49  	if err == nil {
    50  		return true, nil
    51  	}
    52  	if os.IsNotExist(err) {
    53  		return false, nil
    54  	}
    55  	return false, err
    56  }
    57  
    58  // Runs the tests derived from the XSLT 1.0 specification examples
    59  func TestXsltREC(t *testing.T) {
    60  	var passed []string
    61  	d, _ := os.Open("testdata/REC")
    62  	fi, _ := d.Readdir(-1)
    63  	for _, f := range fi {
    64  		if f.Mode().IsRegular() && path.Ext(f.Name()) == ".xsl" {
    65  			if f.Name() == "test-7.1.1.xsl" {
    66  				fmt.Println("skipping REC/test-7.1.1 due to inconsistent namespace declaration ordering")
    67  				continue
    68  			}
    69  			xslname := path.Join("testdata/REC", f.Name())
    70  			b := xslname[0 : len(xslname)-4]
    71  			inName := b + ".xml"
    72  			outName := b + ".out"
    73  			ii, _ := exists(inName)
    74  			oo, _ := exists(outName)
    75  			if ii && oo {
    76  				ok := runXslTest(t, xslname, inName, outName)
    77  				if ok {
    78  					passed = append(passed, xslname)
    79  				}
    80  			} else {
    81  				// can use this to debug if tests suddenly disappear
    82  				//fmt.Println("Cannot test", xslname)
    83  			}
    84  		}
    85  	}
    86  	fmt.Println("passed", len(passed), "tests")
    87  }
    88  
    89  // Tests the first full example presented in the XSLT 1.0 spec
    90  func TestXsltRECexample1(t *testing.T) {
    91  	xslFile := "testdata/REC1/doc.xsl"
    92  	inputXml := "testdata/REC1/doc.xml"
    93  	outputXml := "testdata/REC1/result.xml"
    94  
    95  	runXslTest(t, xslFile, inputXml, outputXml)
    96  }
    97  
    98  // Tests the second full example presented in the XSLT 1.0 spec
    99  func TestXsltRECexample2(t *testing.T) {
   100  	inputXml := "testdata/REC2/data.xml"
   101  
   102  	runXslTest(t, "testdata/REC2/html.xsl", inputXml, "testdata/REC2/html.xml")
   103  	runXslTest(t, "testdata/REC2/svg.xsl", inputXml, "testdata/REC2/svg.xml")
   104  	runXslTest(t, "testdata/REC2/vrml.xsl", inputXml, "testdata/REC2/vrml.xml")
   105  }
   106  
   107  // Test the handling of global parameters
   108  func TestXsltParameters(t *testing.T) {
   109  	testOptions := StylesheetOptions{false, map[string]interface{}{
   110  		"numberVal": 1.0,
   111  		"stringVal": "abcdef",
   112  	}}
   113  	inputXml := "testdata/parameters/data.xml"
   114  	runXslTestWithOptions(t, "testdata/parameters/basic.xsl", inputXml, "testdata/parameters/basic.xml", testOptions)
   115  }
   116  
   117  var genRun = 0
   118  
   119  // convenience function to fix up the paths before running a test
   120  func runGeneralXslTest(t *testing.T, xslFile string) bool {
   121  	//we change into the general directory to duplicate env of libxslt test run
   122  	// unparsed-entity-uri() in particular returns a result relative to the
   123  	// current working directory.
   124  	pwd, _ := os.Getwd()
   125  	defer os.Chdir(pwd)
   126  	_ = os.Chdir("testdata/general")
   127  	xslf := fmt.Sprintf("%v.xsl", xslFile)
   128  	ii := fmt.Sprintf("../docs/%v.xml", xslFile)
   129  	oo := fmt.Sprintf("%v.out", xslFile)
   130  	genRun = genRun + 1
   131  	return runXslTest(t, xslf, ii, oo)
   132  }
   133  
   134  // Runs the general suite of libxslt regression tests
   135  func TestXsltGeneral(t *testing.T) {
   136  	//runGeneralXslTest(t, "items") //doesn't match pattern - how do we run test?
   137  
   138  	runGeneralXslTest(t, "array") // document('')
   139  	runGeneralXslTest(t, "character")
   140  	//runGeneralXslTest(t, "date_add") // EXSL date functions
   141  	runGeneralXslTest(t, "bug-1-")
   142  	runGeneralXslTest(t, "bug-2-")
   143  	runGeneralXslTest(t, "bug-3-")
   144  	runGeneralXslTest(t, "bug-4-")
   145  	//runGeneralXslTest(t, "bug-5-") // rounding issues outputting numbers; UTF-8 casing?
   146  	runGeneralXslTest(t, "bug-6-")
   147  	runGeneralXslTest(t, "bug-7-")
   148  	runGeneralXslTest(t, "bug-8-") //issue resolving namespaces in imported stylesheet
   149  	runGeneralXslTest(t, "bug-9-")
   150  	runGeneralXslTest(t, "bug-10-")
   151  	runGeneralXslTest(t, "bug-11-")
   152  	runGeneralXslTest(t, "bug-12-")
   153  	runGeneralXslTest(t, "bug-13-")
   154  	runGeneralXslTest(t, "bug-14-")
   155  	runGeneralXslTest(t, "bug-15-")
   156  	runGeneralXslTest(t, "bug-16-")
   157  	runGeneralXslTest(t, "bug-17-")
   158  	runGeneralXslTest(t, "bug-18-")
   159  	runGeneralXslTest(t, "bug-19-")
   160  	runGeneralXslTest(t, "bug-20-")
   161  	runGeneralXslTest(t, "bug-21-") // unparsed-entity-uri()
   162  	runGeneralXslTest(t, "bug-22-")
   163  	runGeneralXslTest(t, "bug-23-")
   164  	runGeneralXslTest(t, "bug-24-")
   165  	runGeneralXslTest(t, "bug-25-") // encoding attr when UTF-8 explicitly specified in doc
   166  	runGeneralXslTest(t, "bug-26-")
   167  	runGeneralXslTest(t, "bug-27-")
   168  	runGeneralXslTest(t, "bug-28-")
   169  	runGeneralXslTest(t, "bug-29-") // document('href'); need to resolve to new source document
   170  	runGeneralXslTest(t, "bug-30-")
   171  	runGeneralXslTest(t, "bug-31-")
   172  	runGeneralXslTest(t, "bug-32-")
   173  	runGeneralXslTest(t, "bug-33-")
   174  	runGeneralXslTest(t, "bug-35-")
   175  	runGeneralXslTest(t, "bug-36-") //xsl:include
   176  	runGeneralXslTest(t, "bug-37-") //xsl:include
   177  	//runGeneralXslTest(t, "bug-38-") // handle copy-of() for namespace nodes
   178  	runGeneralXslTest(t, "bug-39-")
   179  	runGeneralXslTest(t, "bug-40-") //variable scope is global when call-template is invoked
   180  	runGeneralXslTest(t, "bug-41-") //also avoid overwriting global variable using with-param
   181  	runGeneralXslTest(t, "bug-42-") //as 40 but for apply-templates
   182  	runGeneralXslTest(t, "bug-43-") //as 41 but for apply-templates
   183  	runGeneralXslTest(t, "bug-44-") // with-param
   184  	runGeneralXslTest(t, "bug-45-") // ensure params/variables resolve in correct order
   185  	runGeneralXslTest(t, "bug-46-")
   186  	runGeneralXslTest(t, "bug-47-")
   187  	runGeneralXslTest(t, "bug-48-")
   188  	runGeneralXslTest(t, "bug-49-") // global variable defined in terms of inner variable
   189  	runGeneralXslTest(t, "bug-50-")
   190  	runGeneralXslTest(t, "bug-52") //unparsed-entity-uri with nodeset argument
   191  	runGeneralXslTest(t, "bug-53") // depends on DTD processing of ATTLIST with default attribute
   192  	//runGeneralXslTest(t, "bug-54") //fails intermittently due to ordering of namespaces
   193  	runGeneralXslTest(t, "bug-55")
   194  	//runGeneralXslTest(t, "bug-56") // unsure what's going on here
   195  	runGeneralXslTest(t, "bug-57")
   196  	runGeneralXslTest(t, "bug-59")
   197  	runGeneralXslTest(t, "bug-60") // fallback for unknown XSL element
   198  	//runGeneralXslTest(t, "bug-61") // format-number outputs NaN correctly
   199  	runGeneralXslTest(t, "bug-62")
   200  	//runGeneralXslTest(t, "bug-63") //resolve namespace nodes and relative paths
   201  	runGeneralXslTest(t, "bug-64")
   202  	//runGeneralXslTest(t, "bug-65") // libxslt:node-set
   203  	runGeneralXslTest(t, "bug-66") //current()
   204  	runGeneralXslTest(t, "bug-68")
   205  	runGeneralXslTest(t, "bug-69") // stylesheet and input in iso-8859-1
   206  	runGeneralXslTest(t, "bug-70") // key() - nodeset as arg 2
   207  	//runGeneralXslTest(t, "bug-71") //only fails due to order of NS declarations; need to review spec on that
   208  	runGeneralXslTest(t, "bug-72") //variables declared in RVT
   209  	runGeneralXslTest(t, "bug-73")
   210  	runGeneralXslTest(t, "bug-74")
   211  	//runGeneralXslTest(t, "bug-75") //format-number()
   212  	runGeneralXslTest(t, "bug-76") //issue with count? or variable resolution?
   213  	runGeneralXslTest(t, "bug-77") //handle spaces around OR
   214  	runGeneralXslTest(t, "bug-78")
   215  	runGeneralXslTest(t, "bug-79")
   216  	runGeneralXslTest(t, "bug-80") //fails due to ordering of attributes; review, possibly edit test
   217  	runGeneralXslTest(t, "bug-81") //rounding error in XPath calculation; might be caused by CGO conversion
   218  	//runGeneralXslTest(t, "bug-82") //whitespace interactions; possibly not honoring global preserve-space
   219  	runGeneralXslTest(t, "bug-83")
   220  	runGeneralXslTest(t, "bug-84")
   221  	runGeneralXslTest(t, "bug-86") //getting some unnecessary duplication of namespaces declarations using copy-of
   222  	//runGeneralXslTest(t, "bug-87") //matching on namespace node
   223  	runGeneralXslTest(t, "bug-88")
   224  	runGeneralXslTest(t, "bug-89") //fails with stricter parser
   225  	runGeneralXslTest(t, "bug-90") // CDATA handling
   226  	runGeneralXslTest(t, "bug-91") // disable-output-escaping attribute
   227  	//runGeneralXslTest(t, "bug-92") //libxml2 doesn't output the xs namespace here; why not?
   228  	//runGeneralXslTest(t, "bug-93") // presence of xsl:output in imported stylesheets should cause effective merge
   229  	runGeneralXslTest(t, "bug-94") //variable/param confusion
   230  	//runGeneralXslTest(t, "bug-95") //format-number
   231  	runGeneralXslTest(t, "bug-96") //cdata-section-elements
   232  	runGeneralXslTest(t, "bug-97")
   233  	runGeneralXslTest(t, "bug-98")
   234  	//runGeneralXslTest(t, "bug-99") // expects multiple namespace declarations
   235  	//runGeneralXslTest(t, "bug-100") // libxslt:test extension element
   236  	runGeneralXslTest(t, "bug-101") // xsl:element with default namespace
   237  	//runGeneralXslTest(t, "bug-102") // imported xsl:attribute-set
   238  	runGeneralXslTest(t, "bug-103") //copy-of needs to explicitly set empty namespace when needed
   239  	//runGeneralXslTest(t, "bug-104") //copy-of should preserve attr prefix if plausible
   240  	runGeneralXslTest(t, "bug-105")
   241  	runGeneralXslTest(t, "bug-106") //copy-of
   242  	runGeneralXslTest(t, "bug-107")
   243  	runGeneralXslTest(t, "bug-108")
   244  	runGeneralXslTest(t, "bug-109") // disable-output-escaping
   245  	runGeneralXslTest(t, "bug-110") //generate-id()
   246  	runGeneralXslTest(t, "bug-111") //exsl:node-set()
   247  	runGeneralXslTest(t, "bug-112") //exsl:node-set()
   248  	runGeneralXslTest(t, "bug-113") // stylesheet and parser in ISO-8859-1
   249  	runGeneralXslTest(t, "bug-114")
   250  	runGeneralXslTest(t, "bug-115") //exsl:node-set()
   251  	runGeneralXslTest(t, "bug-116")
   252  	runGeneralXslTest(t, "bug-117") //exsl declaration should not be in output
   253  	runGeneralXslTest(t, "bug-118") //copy-of
   254  	runGeneralXslTest(t, "bug-119")
   255  	//runGeneralXslTest(t, "bug-120") //xsl:sort with data-type; interaction with copy-of?
   256  	runGeneralXslTest(t, "bug-121")
   257  	//runGeneralXslTest(t, "bug-122") //namespace nodes
   258  	runGeneralXslTest(t, "bug-123")
   259  	//runGeneralXslTest(t, "bug-124") //namespace declared with multiple prefixes; really a bug?
   260  	//runGeneralXslTest(t, "bug-125") //unclear; needs further investigation
   261  	//runGeneralXslTest(t, "bug-126") //tests for bugs in AVT parsing
   262  	runGeneralXslTest(t, "bug-127")
   263  	//runGeneralXslTest(t, "bug-128") //multiple keys with the same name; need to look at spec
   264  	runGeneralXslTest(t, "bug-129") //cdata-section-elements
   265  	//runGeneralXslTest(t, "bug-130") //document('href') and import; different default namespace in imported stylesheet
   266  	//runGeneralXslTest(t, "bug-131") // attribute-set combine import defs
   267  	runGeneralXslTest(t, "bug-132")
   268  	//runGeneralXslTest(t, "bug-133") // interaction between key, generate-id?
   269  	//runGeneralXslTest(t, "bug-134") // xsl:key match "node()[self::sect]" should be same as match "sect" but is not; context issue??
   270  	//runGeneralXslTest(t, "bug-135") // same as 134
   271  	runGeneralXslTest(t, "bug-136")
   272  	//runGeneralXslTest(t, "bug-137") // EXSLT func
   273  	runGeneralXslTest(t, "bug-138")
   274  	//runGeneralXslTest(t, "bug-139") //extra output of entity definitions (why?)
   275  	runGeneralXslTest(t, "bug-140") // failed due to standalone
   276  	runGeneralXslTest(t, "bug-141")
   277  	//runGeneralXslTest(t, "bug-142") //lang() function doing strange things?
   278  	//runGeneralXslTest(t, "bug-143") //exposes a timing bug in global variable definitions
   279  	runGeneralXslTest(t, "bug-144")
   280  	runGeneralXslTest(t, "bug-145") //should result in no output (calling template that doesn't exist)
   281  	//runGeneralXslTest(t, "bug-146") // funny looking key definition plus encoding issue
   282  	//runGeneralXslTest(t, "bug-147") //looks like import precedence related
   283  	runGeneralXslTest(t, "bug-148")
   284  	runGeneralXslTest(t, "bug-149")
   285  	//runGeneralXslTest(t, "bug-150") //scoping of namespace definitions on literal result elements
   286  	runGeneralXslTest(t, "bug-151") // outputs just the declaration; should be nothing
   287  	//runGeneralXslTest(t, "bug-152") //libxml2 inserts a content-type meta tag; unsure why
   288  	runGeneralXslTest(t, "bug-153") //document('href') and current()
   289  	runGeneralXslTest(t, "bug-154") //should have no output
   290  	runGeneralXslTest(t, "bug-155")
   291  	runGeneralXslTest(t, "bug-156")
   292  	runGeneralXslTest(t, "bug-157")
   293  	runGeneralXslTest(t, "bug-158")
   294  	//runGeneralXslTest(t, "bug-159") //escape entities appropriately if encoding=ascii
   295  	//runGeneralXslTest(t, "bug-160") // match criteria seems to be the issue here
   296  	runGeneralXslTest(t, "bug-161")
   297  	runGeneralXslTest(t, "bug-163")
   298  	runGeneralXslTest(t, "bug-164")
   299  	//runGeneralXslTest(t, "bug-165") //xpath with unresolvable variable in predicate; differs in number of blank lines produced
   300  	//runGeneralXslTest(t, "bug-166") //need to look closer; slow and much output!
   301  	runGeneralXslTest(t, "bug-167")
   302  	//runGeneralXslTest(t, "bug-168") //looks like AVT torture test
   303  	//runGeneralXslTest(t, "bug-169") // not selecting correct output encoding?
   304  	runGeneralXslTest(t, "bug-170")
   305  	runGeneralXslTest(t, "bug-171")
   306  	runGeneralXslTest(t, "bug-172") //seems to be bug in xsl:choose (matches when test but no output)
   307  	//runGeneralXslTest(t, "bug-173") //extra newline on output?
   308  	//runGeneralXslTest(t, "bug-174") //exslt:func
   309  	//runGeneralXslTest(t, "bug-175") //wrong output encoding/doctype for html output
   310  	runGeneralXslTest(t, "bug-176")
   311  	runGeneralXslTest(t, "bug-177") //should not create namespace declaration for built-in xml namespace
   312  	//runGeneralXslTest(t, "bug-178") //exslt:func
   313  	//runGeneralXslTest(t, "bug-179") // xsl:element/@namespace don't need to explicitly create namespace already in scope
   314  	//runGeneralXslTest(t, "bug-180") //expects no output
   315  	//runGeneralXslTest(t, "bug-181") //this appears to be template priority bug
   316  	//runGeneralXslTest(t, "bug-182") //text()[2] should match something
   317  	fmt.Println("passed", genRun, "tests")
   318  }
   319  
   320  // sample usage for parse stylesheet
   321  func ExampleParseStylesheet() {
   322  	//parse the stylesheet
   323  	style, _ := xml.ReadFile("testdata/test.xsl", xml.StrictParseOption)
   324  	stylesheet, _ := ParseStylesheet(style, "testdata/test.xsl")
   325  
   326  	//process the input
   327  	input, _ := xml.ReadFile("testdata/test.xml", xml.StrictParseOption)
   328  	output, _ := stylesheet.Process(input, StylesheetOptions{false, nil})
   329  	fmt.Println(output)
   330  }