gonum.org/v1/gonum@v0.14.0/graph/formats/rdf/rdf_test.go (about)

     1  // Copyright ©2020 The Gonum Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package rdf
     6  
     7  import (
     8  	"archive/tar"
     9  	"compress/gzip"
    10  	"fmt"
    11  	"io"
    12  	"os"
    13  	"path/filepath"
    14  	"reflect"
    15  	"strings"
    16  	"testing"
    17  )
    18  
    19  func TestRDFWorkingGroupSuite(t *testing.T) {
    20  	for _, file := range []string{
    21  		"ntriple_tests.tar.gz",
    22  		"nquad_tests.tar.gz",
    23  	} {
    24  		suite, err := os.Open(filepath.Join("testdata", file))
    25  		if err != nil {
    26  			t.Fatalf("Failed to open test suite in %q: %v", file, err)
    27  		}
    28  		defer suite.Close()
    29  
    30  		r, err := gzip.NewReader(suite)
    31  		if err != nil {
    32  			t.Fatalf("Failed to uncompress test suite in %q: %v", file, err)
    33  		}
    34  
    35  		tr := tar.NewReader(r)
    36  		for {
    37  			h, err := tr.Next()
    38  			if err != nil {
    39  				if err == io.EOF {
    40  					break
    41  				}
    42  				t.Fatalf("Unexpected error while reading suite archive: %v", err)
    43  			}
    44  
    45  			h.Name = filepath.Base(h.Name)
    46  			if filepath.Ext(h.Name) != ".nt" && filepath.Ext(h.Name) != ".nq" {
    47  				continue
    48  			}
    49  			if _, ok := testSuite[h.Name]; !ok {
    50  				t.Errorf("Missing test suite item %q", h.Name)
    51  				continue
    52  			}
    53  
    54  			isBad := strings.Contains(h.Name, "bad")
    55  
    56  			var got []statement
    57  			dec := NewDecoder(tr)
    58  			for i := 0; ; i++ {
    59  				s, err := dec.Unmarshal()
    60  				if err == io.EOF {
    61  					break
    62  				}
    63  				gotBad := err != nil
    64  				if gotBad != isBad {
    65  					t.Errorf("Unexpected error return for test suite item %q, got: %v", h.Name, err)
    66  				}
    67  
    68  				var subj, pred, obj, lab term
    69  				if s != nil {
    70  					subj.text, subj.qual, subj.kind, _ = s.Subject.Parts()
    71  					pred.text, pred.qual, pred.kind, _ = s.Predicate.Parts()
    72  					obj.text, obj.qual, obj.kind, _ = s.Object.Parts()
    73  					lab.text, lab.qual, lab.kind, _ = s.Label.Parts()
    74  					if lab.text == "" {
    75  						lab = term{}
    76  					}
    77  					got = append(got, statement{testSuite[h.Name][i].input, subj, pred, obj, lab})
    78  				}
    79  
    80  				if !gotBad {
    81  					_, err = ParseNQuad(s.String())
    82  					if err != nil {
    83  						t.Errorf("Unexpected error return for valid statement in test suite item %q (%#v) got: %v rendered as\n%[2]s", h.Name, s, err)
    84  					}
    85  
    86  					st, err := termFor(subj.text, subj.qual, subj.kind)
    87  					if err != nil {
    88  						t.Errorf("Unexpected error return for valid subject in test suite item %q (%#v) got: %v rendered as\n%[2]s", h.Name, s, err)
    89  					}
    90  					pt, err := termFor(pred.text, pred.qual, pred.kind)
    91  					if err != nil {
    92  						t.Errorf("Unexpected error return for valid predicate in test suite item %q (%#v) got: %v rendered as\n%[2]s", h.Name, s, err)
    93  					}
    94  					ot, err := termFor(obj.text, obj.qual, obj.kind)
    95  					if err != nil {
    96  						t.Errorf("Unexpected error return for valid object in test suite item %q (%#v) got: %v rendered as\n%[2]s", h.Name, s, err)
    97  					}
    98  					lt, err := termFor(lab.text, lab.qual, lab.kind)
    99  					if err != nil {
   100  						t.Errorf("Unexpected error return for valid label in test suite item %q (%#v) got: %v rendered as\n%[2]s", h.Name, s, err)
   101  					}
   102  
   103  					// We can't check that we recreate the original from the test suite
   104  					// due to escaping, but we can check for a second pass through the
   105  					// round-trip.
   106  					c := &Statement{Subject: st, Predicate: pt, Object: ot, Label: lt}
   107  					pc, err := ParseNQuad(c.String())
   108  					if err != nil {
   109  						t.Errorf("Unexpected error return for reconstructed statement in test suite item %q (%#v) got: %v rendered as\n%[2]s", h.Name, s, err)
   110  					}
   111  					if !reflect.DeepEqual(c, pc) {
   112  						t.Errorf("Unexpected reconstruction:\norig:  %#v\ncons:  %#v\nparsed:%#v", s, c, pc)
   113  					}
   114  				}
   115  			}
   116  
   117  			if !reflect.DeepEqual(testSuite[h.Name], got) {
   118  				t.Errorf("Unexpected result for test suite item %q", h.Name)
   119  			}
   120  		}
   121  	}
   122  }
   123  
   124  func termFor(text, qual string, kind Kind) (Term, error) {
   125  	switch kind {
   126  	case Invalid:
   127  		return Term{}, nil
   128  	case Blank:
   129  		return NewBlankTerm(text)
   130  	case IRI:
   131  		return NewIRITerm(text)
   132  	case Literal:
   133  		return NewLiteralTerm(text, qual)
   134  	default:
   135  		panic(fmt.Sprintf("bad test kind=%d", kind))
   136  	}
   137  }
   138  
   139  var escapeSequenceTests = []struct {
   140  	escaped      string
   141  	unEscaped    string
   142  	canRoundTrip bool
   143  }{
   144  	{escaped: `plain text!`, unEscaped: "plain text!", canRoundTrip: true},
   145  	{escaped: `\t`, unEscaped: "\t", canRoundTrip: false},
   146  	{escaped: `\b`, unEscaped: "\b", canRoundTrip: false},
   147  	{escaped: `\n`, unEscaped: "\n", canRoundTrip: true},
   148  	{escaped: `\r`, unEscaped: "\r", canRoundTrip: true},
   149  	{escaped: `\f`, unEscaped: "\f", canRoundTrip: false},
   150  	{escaped: `\\`, unEscaped: "\\", canRoundTrip: true},
   151  	{escaped: `\u0080`, unEscaped: "\u0080", canRoundTrip: true},
   152  	{escaped: `\U00000080`, unEscaped: "\u0080", canRoundTrip: false},
   153  	{escaped: `\t\b\n\r\f\"'\\`, unEscaped: "\t\b\n\r\f\"'\\", canRoundTrip: false},
   154  
   155  	{escaped: `\t\u0080`, unEscaped: "\t\u0080", canRoundTrip: false},
   156  	{escaped: `\b\U00000080`, unEscaped: "\b\u0080", canRoundTrip: false},
   157  	{escaped: `\u0080\n`, unEscaped: "\u0080\n", canRoundTrip: true},
   158  	{escaped: `\U00000080\r`, unEscaped: "\u0080\r", canRoundTrip: false},
   159  	{escaped: `\u00b7\f\U000000b7`, unEscaped: "·\f·", canRoundTrip: false},
   160  	{escaped: `\U000000b7\\\u00b7`, unEscaped: "·\\·", canRoundTrip: false},
   161  	{escaped: `\U00010105\\\U00010106`, unEscaped: "\U00010105\\\U00010106", canRoundTrip: true},
   162  }
   163  
   164  func TestUnescape(t *testing.T) {
   165  	for _, test := range escapeSequenceTests {
   166  		got := unEscape([]rune(test.escaped))
   167  		if got != test.unEscaped {
   168  			t.Errorf("Failed to properly unescape %q, got:%q want:%q", test.escaped, got, test.unEscaped)
   169  		}
   170  
   171  		if test.canRoundTrip {
   172  			got = escape("", test.unEscaped, "")
   173  			if got != test.escaped {
   174  				t.Errorf("Failed to properly escape %q, got:%q want:%q", test.unEscaped, got, test.escaped)
   175  			}
   176  			got = escape(`"`, test.unEscaped, `"`)
   177  			if got != `"`+test.escaped+`"` {
   178  				t.Errorf("Failed to properly escape %q quoted, got:%q want:%q", test.unEscaped, got, `"`+test.escaped+`"`)
   179  			}
   180  		}
   181  	}
   182  }