guile-rdf/test-modules/online.scm

online.scm

1
;;;; Copyright (C) 2020 Julien Lepiller <julien@lepiller.eu>
2
;;;; 
3
;;;; This library is free software; you can redistribute it and/or
4
;;;; modify it under the terms of the GNU Lesser General Public
5
;;;; License as published by the Free Software Foundation; either
6
;;;; version 3 of the License, or (at your option) any later version.
7
;;;; 
8
;;;; This library is distributed in the hope that it will be useful,
9
;;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
10
;;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11
;;;; Lesser General Public License for more details.
12
;;;; 
13
;;;; You should have received a copy of the GNU Lesser General Public
14
;;;; License along with this library; if not, write to the Free Software
15
;;;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16
;;;; 
17
18
(define-module (test-modules online)
19
  #:use-module (ice-9 match)
20
  #:use-module (rnrs bytevectors)
21
  #:use-module (srfi srfi-1)
22
  #:use-module (test-modules result)
23
  #:use-module ((rdf entailment rdf) #:prefix rdf:)
24
  #:use-module ((rdf entailment simple) #:prefix simple:)
25
  #:use-module (rdf rdf)
26
  #:use-module ((rdf xsd) #:prefix xsd:)
27
  #:use-module (srfi srfi-1)
28
  #:use-module (turtle tordf)
29
  #:use-module (web client)
30
  #:use-module (web response)
31
  #:export (run-test-suite
32
            run-test-suites))
33
34
(define (find-rest node graph)
35
  (rdf-triple-object
36
    (car
37
      (filter
38
        (lambda (triple)
39
          (and (equal? (rdf-triple-subject triple) node)
40
               (equal? (rdf-triple-predicate triple)
41
                       (string-append "http://www.w3.org/1999/02/22-rdf-syntax-ns"
42
                                      "#rest"))))
43
        graph))))
44
45
(define (find-first node graph)
46
  (rdf-triple-object
47
    (car
48
      (filter
49
        (lambda (triple)
50
          (and (equal? (rdf-triple-subject triple) node)
51
               (equal? (rdf-triple-predicate triple)
52
                       (string-append "http://www.w3.org/1999/02/22-rdf-syntax-ns"
53
                                      "#first"))))
54
        graph))))
55
56
(define (find-list node graph)
57
  (if (blank-node? node)
58
      (let loop ((node node) (result '()))
59
        (let ((first (find-first node graph))
60
              (node (find-rest node graph)))
61
          (if (blank-node? node)
62
              (loop node (cons first result))
63
              (cons first result))))
64
      '()))
65
66
(define (get-objects triples predicate)
67
  (map
68
    rdf-triple-object
69
    (filter
70
      (lambda (t)
71
        (equal? (rdf-triple-predicate t) predicate))
72
      triples)))
73
74
(define (lexical->value value)
75
  (cond
76
    ((rdf-literal? value)
77
     (rdf-literal-lexical-form value))
78
    ((blank-node? value)
79
     (string-append "_:" (number->string value)))
80
    (else value)))
81
82
(define (execute-test test)
83
  (let* ((predicates (test-case-document test))
84
         (type (car (get-objects predicates "http://www.w3.org/1999/02/22-rdf-syntax-ns#type")))
85
         (type (car (reverse (string-split type #\#))))
86
         (action (car (get-objects predicates "http://www.w3.org/2001/sw/DataAccess/tests/test-manifest#action"))))
87
    (turtle->rdf (get-test-doc action) action)))
88
89
(define (run-test test)
90
  (let* ((predicates (test-case-document test))
91
         (type (car (get-objects predicates "http://www.w3.org/1999/02/22-rdf-syntax-ns#type")))
92
         (type (car (reverse (string-split type #\#))))
93
         (result
94
           (catch #t
95
             (lambda ()
96
               (execute-test test))
97
             (lambda (key . value)
98
               (cons key value)))))
99
    (cond
100
      ((member type '("TestTurtlePositiveSyntax" "TestTriGPositiveSyntax"
101
                      "TestNTriplesPositiveSyntax" "TestNQuadsPositiveSyntax"))
102
       (match result
103
         (((? symbol? key) . value)
104
          (update-test-case test
105
            #:result 'fail
106
            #:reason (format #f "failed with ~a: ~a" key value)))
107
         (_ (update-test-case test #:result 'pass))))
108
      ((member type '("TestTurtleNegativeSyntax" "TestTriGNegativeSyntax"
109
                      "TestNTriplesNegativeSyntax" "TestNQuadsNegativeSyntax"
110
                      "TestXMLNegativeSyntax" "TestTurtleNegativeEval"))
111
       (match result
112
         (((? symbol? key) . value) (update-test-case test #:result 'pass))
113
         (_ (update-test-case test
114
              #:result 'fail
115
              #:reason "Expected failure but got success"))))
116
      ((equal? type "TestTurtleEval")
117
       (let* ((expected (car (get-objects predicates "http://www.w3.org/2001/sw/DataAccess/tests/test-manifest#result")))
118
              (expected
119
                (catch #t
120
                  (lambda ()
121
                    (if expected
122
                        (turtle->rdf (get-test-doc expected) expected)
123
                        #f))
124
                  (lambda (key . value)
125
                    (cons key value)))))
126
         (match result
127
           (((? symbol? key) . value)
128
            (update-test-case test
129
              #:result 'fail
130
              #:reason (format #f "failed with ~a: ~a" key value)))
131
           (_
132
             (if (rdf-isomorphic? result expected)
133
                 (update-test-case test #:result 'pass)
134
                 (update-test-case test
135
                   #:result 'fail
136
                   #:reason (format #f "expected ~a but got ~a"
137
                                    expected result)))))))
138
      ((member type '("PositiveEntailmentTest" "NegativeEntailmentTest"))
139
       (pk 'predicates predicates)
140
       (let* ((regime (rdf-literal-lexical-form
141
                        (car
142
                          (get-objects
143
                            predicates
144
                            (string-append
145
                              "http://www.w3.org/2001/sw/DataAccess/tests/"
146
                              "test-manifest#entailmentRegime")))))
147
              (recognized
148
                (car
149
                  (pk 'recognized-nodes
150
                  (get-objects
151
                    predicates
152
                    (string-append "http://www.w3.org/2001/sw/DataAccess/tests/"
153
                                   "test-manifest#recognizedDatatypes"))))
154
                )
155
              (recognized (pk 'lst-reco (find-list recognized predicates)))
156
              (recognized
157
                (map
158
                  (lambda (iri)
159
                    (let loop ((types xsd:datatypes))
160
                      (match types
161
                        (() #f)
162
                        ((type types ...)
163
                         (if (member iri (rdf-datatype-iris type))
164
                             (pk 'recognized-type type)
165
                             (loop types))))))
166
                  recognized))
167
              (recognized (pk 'reco (append (list xsd:string rdf:langString) recognized)))
168
              (expected
169
                (car
170
                  (get-objects
171
                    predicates
172
                    (string-append "http://www.w3.org/2001/sw/DataAccess/tests/"
173
                                   "test-manifest#result"))))
174
              (expected
175
                (catch #t
176
                  (lambda ()
177
                    (if expected
178
                        (turtle->rdf (get-test-doc expected) expected)
179
                        #f))
180
                  (lambda (key . value)
181
                    (cons key value)))))
182
         (match regime
183
           ("simple"
184
            (if (if (equal? expected #f)
185
                    (simple:consistent-graph? result)
186
                    (simple:entails? result expected))
187
                (if (equal? type "PositiveEntailmentTest")
188
                    (update-test-case test #:result 'pass)
189
                    (update-test-case test
190
                      #:result 'fail
191
                      #:reason "Expected negative result, got positive"))
192
                (if (equal? type "PositiveEntailmentTest")
193
                    (update-test-case test
194
                      #:result 'fail
195
                      #:reason (format #f "Expected positive result, got negative"))
196
                    (update-test-case test #:result 'pass))))
197
           ("RDF"
198
            (if (if (equal? expected #f)
199
                    (rdf:consistent-graph? result)
200
                    (rdf:entails? (recognize result recognized)
201
                                  (recognize expected recognized)))
202
                (if (equal? type "PositiveEntailmentTest")
203
                    (update-test-case test #:result 'pass)
204
                    (update-test-case test
205
                      #:result 'fail
206
                      #:reason "Expected negative result, got positive"))
207
                (if (equal? type "PositiveEntailmentTest")
208
                    (update-test-case test
209
                      #:result 'fail
210
                      #:reason (format #f "Expected positive result, got negative"))
211
                    (update-test-case test #:result 'pass))))
212
           (_ (update-test-case test
213
                #:result 'skip
214
                #:reason (format #f "Unrecognized entailment regime: ~a"
215
                                 regime))))))
216
      (else
217
        (update-test-case test
218
          #:result 'skip
219
          #:reason (format #f "Unrecognized test type: ~a" type))))))
220
221
(define (run-tests tests expected-failures driver)
222
  "Run all the tests of the @var{tests} test suite, using identifiers starting
223
from @var{id}.  Return is undefined."
224
  (fold
225
    (lambda (test results)
226
      (let* ((result (run-test test))
227
             (result
228
               (if (assoc-ref expected-failures (test-case-id test))
229
                   (update-test-case result
230
                     #:result (cond
231
                                ((equal? 'skip (test-case-result result))
232
                                 'skip)
233
                                ((equal? 'fail (test-case-result result))
234
                                 'xfail)
235
                                ((equal? 'pass (test-case-result result))
236
                                 'xpass))
237
                     #:reason (assoc-ref expected-failures (test-case-id test)))
238
                   result)))
239
        ((test-driver-print driver) result)
240
        (cons result results)))
241
    '()
242
    tests))
243
244
(define (get-test-doc url)
245
  "Get a test suite object from the manifest at @var{url}."
246
  (call-with-values
247
    (lambda ()
248
      (http-get url))
249
    (lambda (hdr body)
250
      (if (equal? (response-code hdr) 200)
251
          (if (string? body)
252
              body
253
              (utf8->string body))
254
          (throw 'error-fetching-test-manifest (response-code hdr))))))
255
256
(define* (get-test-plan url #:key (num 1))
257
  (define document (get-test-doc url))
258
259
  (define manifest (turtle->rdf document url))
260
261
  (define tests-node
262
    (rdf-triple-object
263
      (car
264
        (filter
265
          (lambda (triple)
266
            (and (equal? (rdf-triple-subject triple) url)
267
                 (equal? (rdf-triple-predicate triple)
268
                         (string-append "http://www.w3.org/2001/sw/DataAccess/"
269
                                        "tests/test-manifest#entries"))))
270
          manifest))))
271
272
  (define tests (find-list tests-node manifest))
273
274
  (define (subgraph-at graph node)
275
    (let ((nodes (filter
276
                   (lambda (t)
277
                     (equal? (rdf-triple-subject t) node))
278
                   graph)))
279
      (if (null? nodes)
280
          '()
281
          (apply append nodes
282
                 (map
283
                   (lambda (n)
284
                     (subgraph-at graph (rdf-triple-object n)))
285
                   nodes)))))
286
287
  (cdr
288
    (fold
289
      (lambda (test result)
290
        (let* ((num (car result))
291
               (result (cdr result))
292
               (test-predicates (subgraph-at manifest test))
293
               (name (lexical->value (car (get-objects test-predicates "http://www.w3.org/2001/sw/DataAccess/tests/test-manifest#name"))))
294
               (description (lexical->value (car (get-objects test-predicates "http://www.w3.org/2000/01/rdf-schema#comment")))))
295
          (cons (+ 1 num)
296
                (cons (make-test-case test num name description test-predicates
297
                                      #f #f)
298
                      result))))
299
      `(,num . ())
300
      tests)))
301
302
(define (run-test-suite manifest expected-failures driver)
303
  "Run a test suite described by @var{manifest}."
304
  (let* ((plan (reverse (get-test-plan manifest))))
305
    ((test-driver-init driver) plan)
306
    ((test-driver-finalize driver) (run-tests plan expected-failures driver))))
307
308
(define (run-test-suites manifests expected-failures driver)
309
  "Run multiple test suites described by @var{manifests}."
310
  (let* ((plan
311
           (fold
312
             (lambda (manifest plan)
313
               (append plan (reverse (get-test-plan
314
                                       manifest #:num (+ (length plan) 1)))))
315
             '()
316
             manifests)))
317
    ((test-driver-init driver) plan)
318
    ((test-driver-finalize driver) (run-tests plan expected-failures driver))))
319