diff --git a/.github/workflows/Arch.yml b/.github/workflows/Arch.yml new file mode 100644 index 0000000..f5f9da3 --- /dev/null +++ b/.github/workflows/Arch.yml @@ -0,0 +1,35 @@ +# This workflow will build a golang project +# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-go + +name: Go + +on: + push: + branches: ["master"] + pull_request: + branches: ["master"] + +jobs: + build: + runs-on: ubuntu-latest + + container: + image: archlinux:latest + + steps: + - uses: actions/checkout@v3 + + - name: Set Up Arch Linux + run: | + pacman -Syy --noconfirm + pacman -Syu --noconfirm + pacman -S --noconfirm base-devel + pacman -S --noconfirm libxml2 + + - name: Set up Go + uses: actions/setup-go@v4 + with: + go-version: "1.21" + + - name: Test + run: go test ./... diff --git a/clib/clib.go b/clib/clib.go index f2132b3..687945f 100644 --- a/clib/clib.go +++ b/clib/clib.go @@ -58,13 +58,13 @@ static inline void MY_xmlFree(void *p) { // Macro wrapper function. cgo cannot detect function-like macros, // so this is how we avoid it static inline xmlError* MY_xmlLastError() { - return xmlGetLastError(); + return (xmlError*) xmlGetLastError(); } // Macro wrapper function. cgo cannot detect function-like macros, // so this is how we avoid it static inline xmlError* MY_xmlCtxtLastError(void *ctx) { - return xmlCtxtGetLastError(ctx); + return (xmlError*) xmlCtxtGetLastError(ctx); } // Change xmlIndentTreeOutput global, return old value, so caller can diff --git a/dom/document_test.go b/dom/document_test.go index 072c173..6969f24 100644 --- a/dom/document_test.go +++ b/dom/document_test.go @@ -265,40 +265,40 @@ func TestDocumentCreateAttributeNS(t *testing.T) { t.Errorf("Failed to create Element node: %s", err) return } - d.SetDocumentElement(elem) + _ = d.SetDocumentElement(elem) attr, err := d.CreateAttribute("attr", "e & f") if err != nil { t.Errorf("Failed to create Attribute node: %s", err) return } - elem.AddChild(attr) + _ = elem.AddChild(attr) if elem.String() != `` { t.Errorf(`Expected String '', got '%s'`, elem.String()) return } - elem.RemoveAttribute("attr") + _ = elem.RemoveAttribute("attr") attr, err = d.CreateAttributeNS("", "attr2", "a & b") if err != nil { t.Errorf("Failed to create Attribute node: %s", err) return } - elem.AddChild(attr) + _ = elem.AddChild(attr) if elem.String() != `` { t.Errorf(`Expected String '', got '%s'`, elem.String()) return } - elem.RemoveAttribute("attr2") + _ = elem.RemoveAttribute("attr2") attr, err = d.CreateAttributeNS("http://kungfoo", "foo:attr3", "g & h") if err != nil { t.Errorf("Failed to create Attribute node: %s", err) return } - elem.AddChild(attr) + _ = elem.AddChild(attr) if elem.String() != `` { t.Errorf(`Expected String '', got '%s'`, elem.String()) @@ -318,7 +318,7 @@ func TestDocumentCreateAttributeNS(t *testing.T) { t.Errorf("Failed to create Element node: %s", err) return } - d.SetDocumentElement(elem) + _ = d.SetDocumentElement(elem) attr, err := d.CreateAttributeNS("http://kungfoo", "kung:foo", "bar") if err != nil { @@ -355,7 +355,7 @@ func TestDocumentCreateAttributeNS(t *testing.T) { t.Errorf("Failed to create Element node: %s", err) return } - d.SetDocumentElement(elem) + _ = d.SetDocumentElement(elem) badnames := []string{";", "&", "<><", "/", "1A"} for _, name := range badnames { diff --git a/dom/node_test.go b/dom/node_test.go index 2755333..70a6bd5 100644 --- a/dom/node_test.go +++ b/dom/node_test.go @@ -1,10 +1,11 @@ -package dom +package dom_test import ( "fmt" "testing" "github.com/lestrrat-go/libxml2/clib" + . "github.com/lestrrat-go/libxml2/dom" "github.com/lestrrat-go/libxml2/types" "github.com/stretchr/testify/assert" ) @@ -123,15 +124,15 @@ func TestDOM(t *testing.T) { return } - doc.SetDocumentElement(root) + _ = doc.SetDocumentElement(root) var toRemove types.Node for i := 1; i <= 3; i++ { child, err := doc.CreateElement(fmt.Sprintf("child%d", i)) if !assert.NoError(t, err, "dom.CreateElement(child%d) should succeed", i) { return } - child.AppendText(fmt.Sprintf("text%d", i)) - root.AddChild(child) + _ = child.AppendText(fmt.Sprintf("text%d", i)) + _ = root.AddChild(child) if i == 2 { toRemove = child @@ -218,19 +219,19 @@ func TestCreateElementNS(t *testing.T) { if !assert.NoError(t, err, "CreateElementNS should succeed") { return } - doc.SetDocumentElement(root) + _ = doc.SetDocumentElement(root) n1, err := doc.CreateElementNS("http://foo.bar.baz", "foo:n1") if !assert.NoError(t, err, "CreateElementNS should succeed") { return } - root.AddChild(n1) + _ = root.AddChild(n1) n2, err := doc.CreateElementNS("http://foo.bar.baz", "bar:n2") if !assert.NoError(t, err, "CreateElementNS should succeed") { return } - root.AddChild(n2) + _ = root.AddChild(n2) _, err = doc.CreateElementNS("http://foo.bar.baz.quux", "foo:n3") if !assert.Error(t, err, "CreateElementNS should fail") { diff --git a/libxml2.go b/libxml2.go index b17c07e..e610c4b 100644 --- a/libxml2.go +++ b/libxml2.go @@ -15,3 +15,28 @@ correctness will be used. Also, the return values are still shaky -- I'm still debating how to handle error cases gracefully. */ package libxml2 + +import ( + "io" + + "github.com/lestrrat-go/libxml2/parser" + "github.com/lestrrat-go/libxml2/types" +) + +// Parse parses the given buffer and returns a Document. +func Parse(buf []byte, o ...parser.Option) (types.Document, error) { + p := parser.New(o...) + return p.Parse(buf) +} + +// ParseString parses the given string and returns a Document. +func ParseString(s string, o ...parser.Option) (types.Document, error) { + p := parser.New(o...) + return p.ParseString(s) +} + +// ParseReader parses XML from the given io.Reader and returns a Document. +func ParseReader(rdr io.Reader, o ...parser.Option) (types.Document, error) { + p := parser.New(o...) + return p.ParseReader(rdr) +} diff --git a/libxml2_bench_test.go b/libxml2_bench_test.go index fd90d72..3f78412 100644 --- a/libxml2_bench_test.go +++ b/libxml2_bench_test.go @@ -56,7 +56,7 @@ func TestBenchmarkLibxml2Xmlpath(t *testing.T) { if !assert.NoError(t, err, "xpath.NewContext succeeds") { return } - xpc.RegisterNS("atom", "http://www.w3.org/2005/Atom") + _ = xpc.RegisterNS("atom", "http://www.w3.org/2005/Atom") res, err := xpc.Find(`//atom:entry`) if !assert.NoError(t, err, "xpc.Find succeeds") { @@ -97,7 +97,7 @@ func BenchmarkLibxml2Xmlpath(b *testing.B) { if err != nil { b.Fatalf("%s", err) } - xpc.RegisterNS("atom", "http://www.w3.org/2005/Atom") + _ = xpc.RegisterNS("atom", "http://www.w3.org/2005/Atom") for i := 0; i < b.N; i++ { iter := xpath.NodeIter(xpc.Find(`//atom:entry`)) for iter.Next() { @@ -123,7 +123,7 @@ func BenchmarkEncodingXMLDOM(b *testing.B) { for i := 0; i < b.N; i++ { buf.Reset() enc := xml.NewEncoder(&buf) - enc.Encode(f) + _ = enc.Encode(f) } } @@ -142,18 +142,18 @@ func BenchmarkLibxml2DOM(b *testing.B) { d.Free() panic(err) } - d.SetDocumentElement(root) + _ = d.SetDocumentElement(root) f1xml, err := d.CreateElement("Field1") if err != nil { d.Free() panic(err) } - root.AddChild(f1xml) + _ = root.AddChild(f1xml) - f1xml.SetAttribute("Field2", f.Field2) + _ = f1xml.SetAttribute("Field2", f.Field2) - f1xml.AppendText(f.Field1) + _ = f1xml.AppendText(f.Field1) buf.Reset() buf.WriteString(d.Dump(false)) d.Free() diff --git a/libxml2_example_test.go b/libxml2_example_test.go index 2f7a61f..9a246f2 100644 --- a/libxml2_example_test.go +++ b/libxml2_example_test.go @@ -27,7 +27,7 @@ func ExampleXML() { } defer doc.Free() - doc.Walk(func(n types.Node) error { + _ = doc.Walk(func(n types.Node) error { log.Println(n.NodeName()) return nil }) @@ -45,7 +45,7 @@ func ExampleXML() { } defer ctx.Free() - ctx.RegisterNS("atom", "http://www.w3.org/2005/Atom") + _ = ctx.RegisterNS("atom", "http://www.w3.org/2005/Atom") title := xpath.String(ctx.Find("/atom:feed/atom:title/text()")) log.Printf("feed title = %s", title) } @@ -65,7 +65,7 @@ func ExampleHTML() { } defer doc.Free() - doc.Walk(func(n types.Node) error { + _ = doc.Walk(func(n types.Node) error { log.Println(n.NodeName()) return nil }) diff --git a/parser_test.go b/libxml2_test.go similarity index 94% rename from parser_test.go rename to libxml2_test.go index 7e9d5ab..ac1d462 100644 --- a/parser_test.go +++ b/libxml2_test.go @@ -1,9 +1,10 @@ -package libxml2 +package libxml2_test import ( "regexp" "testing" + "github.com/lestrrat-go/libxml2" "github.com/lestrrat-go/libxml2/dom" "github.com/lestrrat-go/libxml2/types" @@ -74,7 +75,7 @@ var ( func parseShouldSucceed(t *testing.T, opts parser.Option, inputs []string) { t.Logf("Test parsing with parser %v", opts) for _, s := range inputs { - d, err := ParseString(s, opts) + d, err := libxml2.ParseString(s, opts) if !assert.NoError(t, err, "Parse should succeed") { return } @@ -84,7 +85,7 @@ func parseShouldSucceed(t *testing.T, opts parser.Option, inputs []string) { func parseShouldFail(t *testing.T, opts parser.Option, inputs []string) { for _, s := range inputs { - d, err := ParseString(s, opts) + d, err := libxml2.ParseString(s, opts) if err == nil { d.Free() t.Errorf("Expected failure to parse '%s'", s) @@ -201,7 +202,7 @@ func TestParseOptionStringer(t *testing.T) { } func TestParseEmpty(t *testing.T) { - doc, err := ParseString(``) + doc, err := libxml2.ParseString(``) if err == nil { t.Errorf("Parse of empty string should fail") defer doc.Free() @@ -245,7 +246,7 @@ func TestParseNoBlanks(t *testing.T) { } func TestRoundtripNoBlanks(t *testing.T) { - doc, err := ParseString(` `, parser.XMLParseNoBlanks) + doc, err := libxml2.ParseString(` `, parser.XMLParseNoBlanks) if err != nil { t.Errorf("failed to parse string: %s", err) return @@ -275,7 +276,7 @@ func TestGHIssue23(t *testing.T) { Goodbye! ` - doc, err := ParseString(src, parser.XMLParseRecover, parser.XMLParseNoWarning, parser.XMLParseNoError) + doc, err := libxml2.ParseString(src, parser.XMLParseRecover, parser.XMLParseNoWarning, parser.XMLParseNoError) if !assert.NoError(t, err, "should pass") { return } @@ -286,7 +287,7 @@ func TestCommentWrapNodeIssue(t *testing.T) { // should wrap comment node const testHTML = "

" - doc, err := ParseHTMLString(testHTML, parser.HTMLParseRecover) + doc, err := libxml2.ParseHTMLString(testHTML, parser.HTMLParseRecover) if err != nil { t.Fatalf("Got error when parsing HTML: %v", err) } @@ -309,7 +310,7 @@ func TestCommentWrapNodeIssue(t *testing.T) { func TestPiWrapNodeIssue(t *testing.T) { // should wrap Pi node const textXML = "\ntest \n" - doc, err := ParseString(textXML) + doc, err := libxml2.ParseString(textXML) if err != nil { t.Fatalf("Got error when parsing xml: %v", err) } @@ -334,7 +335,7 @@ func TestPiWrapNodeIssue(t *testing.T) { func TestGetNonexistentAttributeReturnsRecoverableError(t *testing.T) { const src = `` - doc, err := ParseString(src) + doc, err := libxml2.ParseString(src) if !assert.NoError(t, err, "Should parse") { return } diff --git a/parser.go b/parser.go deleted file mode 100644 index e88ed98..0000000 --- a/parser.go +++ /dev/null @@ -1,26 +0,0 @@ -package libxml2 - -import ( - "io" - - "github.com/lestrrat-go/libxml2/parser" - "github.com/lestrrat-go/libxml2/types" -) - -// Parse parses the given buffer and returns a Document. -func Parse(buf []byte, o ...parser.Option) (types.Document, error) { - p := parser.New(o...) - return p.Parse(buf) -} - -// ParseString parses the given string and returns a Document. -func ParseString(s string, o ...parser.Option) (types.Document, error) { - p := parser.New(o...) - return p.ParseString(s) -} - -// ParseReader parses XML from the given io.Reader and returns a Document. -func ParseReader(rdr io.Reader, o ...parser.Option) (types.Document, error) { - p := parser.New(o...) - return p.ParseReader(rdr) -} diff --git a/parser/parser.go b/parser/parser.go index 9b707f3..7e2cdb6 100644 --- a/parser/parser.go +++ b/parser/parser.go @@ -99,7 +99,9 @@ func (p *Parser) ParseString(s string) (types.Document, error) { if err != nil { return nil, errors.Wrap(err, "failed to create parse context") } - defer func() { _ = ctx.Free() }() + defer func() { + _ = ctx.Free() + }() docptr, err := clib.XMLCtxtReadMemory(ctx, s, "", "", int(p.Options)) if err != nil { diff --git a/xml_test.go b/xml_test.go index e0208c1..9efaf13 100644 --- a/xml_test.go +++ b/xml_test.go @@ -1,10 +1,11 @@ -package libxml2 +package libxml2_test import ( "fmt" "os" "testing" + "github.com/lestrrat-go/libxml2" "github.com/lestrrat-go/libxml2/dom" "github.com/lestrrat-go/libxml2/parser" "github.com/lestrrat-go/libxml2/types" @@ -42,7 +43,7 @@ func TestNamespacedReconciliation(t *testing.T) { if !assert.NoError(t, err, "failed to create document") { return } - d.SetDocumentElement(root) + _ = d.SetDocumentElement(root) if !assert.NoError(t, root.SetNamespace("http://default", "root"), "SetNamespace should succeed") { return } @@ -55,7 +56,7 @@ func TestNamespacedReconciliation(t *testing.T) { if !assert.NoError(t, err, "CreateElementNS should succeed") { return } - root.AddChild(n) + _ = root.AddChild(n) _, err = n.GetAttribute("xmlns") if !assert.Error(t, err, "GetAttribute should fail with not found") || @@ -72,7 +73,7 @@ func TestNamespacedReconciliation(t *testing.T) { if name == "c" { c = child } - n.AddChild(child) + _ = n.AddChild(child) _, err = n.GetAttribute("xmlns:child") if !assert.Error(t, err, "GetAttribute should fail with not found") || !assert.Equal(t, "attribute not found", err.Error(), "error matches") { @@ -96,7 +97,7 @@ func TestNamespacedReconciliation(t *testing.T) { if !assert.NoError(t, err, "creating element with default namespace") { return } - n.AddChild(child) + _ = n.AddChild(child) // XXX This still fails /* @@ -113,7 +114,7 @@ func TestNamespacedReconciliation(t *testing.T) { } func TestRegressionGH7(t *testing.T) { - doc, err := ParseHTMLString(` + doc, err := libxml2.ParseHTMLString(`
@@ -146,11 +147,11 @@ func TestRegressionGH7(t *testing.T) { func TestGHIssue43(t *testing.T) { d := dom.CreateDocument() r, _ := d.CreateElement("root") - r.SetNamespace("http://some.uri", "pfx", true) - d.SetDocumentElement(r) + _ = r.SetNamespace("http://some.uri", "pfx", true) + _ = d.SetDocumentElement(r) e, _ := d.CreateElement("elem") - e.SetNamespace("http://other.uri", "", true) - r.AddChild(e) + _ = e.SetNamespace("http://other.uri", "", true) + _ = r.AddChild(e) s := d.ToString(1, true) if !assert.Contains(t, s, `