1// Copyright 2013 sigu-399 ( https://github.com/sigu-399 )
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//   http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15// author       sigu-399
16// author-github  https://github.com/sigu-399
17// author-mail    sigu.399@gmail.com
18//
19// repository-name  jsonreference
20// repository-desc  An implementation of JSON Reference - Go language
21//
22// description    Automated tests on package.
23//
24// created        03-03-2013
25
26package jsonreference
27
28import (
29	"testing"
30
31	"github.com/go-openapi/jsonpointer"
32	"github.com/stretchr/testify/assert"
33)
34
35func TestIsRoot(t *testing.T) {
36	in := "#"
37	r1, err := New(in)
38	assert.NoError(t, err)
39	assert.True(t, r1.IsRoot())
40
41	in = "#/ok"
42	r1 = MustCreateRef(in)
43	assert.False(t, r1.IsRoot())
44
45	assert.Panics(t, assert.PanicTestFunc(func() {
46		MustCreateRef("%2")
47	}))
48}
49
50// nolint: dupl
51func TestFull(t *testing.T) {
52
53	in := "http://host/path/a/b/c#/f/a/b"
54
55	r1, err := New(in)
56	if err != nil {
57		t.Errorf("New(%v) error %s", in, err.Error())
58	}
59
60	if in != r1.String() {
61		t.Errorf("New(%v) = %v, expect %v", in, r1.String(), in)
62	}
63
64	if r1.HasFragmentOnly != false {
65		t.Errorf("New(%v)::HasFragmentOnly %v expect %v", in, r1.HasFragmentOnly, false)
66	}
67
68	if r1.HasFullURL != true {
69		t.Errorf("New(%v)::HasFullURL %v expect %v", in, r1.HasFullURL, true)
70	}
71
72	if r1.HasURLPathOnly != false {
73		t.Errorf("New(%v)::HasURLPathOnly %v expect %v", in, r1.HasURLPathOnly, false)
74	}
75
76	if r1.HasFileScheme != false {
77		t.Errorf("New(%v)::HasFileScheme %v expect %v", in, r1.HasFileScheme, false)
78	}
79
80	if r1.GetPointer().String() != "/f/a/b" {
81		t.Errorf("New(%v)::GetPointer() %v expect %v", in, r1.GetPointer().String(), "/f/a/b")
82	}
83}
84
85// nolint: dupl
86func TestFullURL(t *testing.T) {
87
88	in := "http://host/path/a/b/c"
89
90	r1, err := New(in)
91	if err != nil {
92		t.Errorf("New(%v) error %s", in, err.Error())
93	}
94
95	if in != r1.String() {
96		t.Errorf("New(%v) = %v, expect %v", in, r1.String(), in)
97	}
98
99	if r1.HasFragmentOnly != false {
100		t.Errorf("New(%v)::HasFragmentOnly %v expect %v", in, r1.HasFragmentOnly, false)
101	}
102
103	if r1.HasFullURL != true {
104		t.Errorf("New(%v)::HasFullURL %v expect %v", in, r1.HasFullURL, true)
105	}
106
107	if r1.HasURLPathOnly != false {
108		t.Errorf("New(%v)::HasURLPathOnly %v expect %v", in, r1.HasURLPathOnly, false)
109	}
110
111	if r1.HasFileScheme != false {
112		t.Errorf("New(%v)::HasFileScheme %v expect %v", in, r1.HasFileScheme, false)
113	}
114
115	if r1.GetPointer().String() != "" {
116		t.Errorf("New(%v)::GetPointer() %v expect %v", in, r1.GetPointer().String(), "")
117	}
118}
119
120func TestFragmentOnly(t *testing.T) {
121
122	in := "#/fragment/only"
123
124	r1, err := New(in)
125	if err != nil {
126		t.Errorf("New(%v) error %s", in, err.Error())
127	}
128
129	if in != r1.String() {
130		t.Errorf("New(%v) = %v, expect %v", in, r1.String(), in)
131	}
132
133	if r1.HasFragmentOnly != true {
134		t.Errorf("New(%v)::HasFragmentOnly %v expect %v", in, r1.HasFragmentOnly, true)
135	}
136
137	if r1.HasFullURL != false {
138		t.Errorf("New(%v)::HasFullURL %v expect %v", in, r1.HasFullURL, false)
139	}
140
141	if r1.HasURLPathOnly != false {
142		t.Errorf("New(%v)::HasURLPathOnly %v expect %v", in, r1.HasURLPathOnly, false)
143	}
144
145	if r1.HasFileScheme != false {
146		t.Errorf("New(%v)::HasFileScheme %v expect %v", in, r1.HasFileScheme, false)
147	}
148
149	if r1.GetPointer().String() != "/fragment/only" {
150		t.Errorf("New(%v)::GetPointer() %v expect %v", in, r1.GetPointer().String(), "/fragment/only")
151	}
152
153	p, _ := jsonpointer.New(r1.referenceURL.Fragment)
154	r2 := Ref{referencePointer: p, HasFragmentOnly: true}
155	assert.Equal(t, r2.String(), in)
156
157	r3 := Ref{referencePointer: p, HasFragmentOnly: false}
158	assert.Equal(t, r3.String(), in[1:])
159}
160
161// nolint: dupl
162func TestURLPathOnly(t *testing.T) {
163
164	in := "/documents/document.json"
165
166	r1, err := New(in)
167	if err != nil {
168		t.Errorf("New(%v) error %s", in, err.Error())
169	}
170
171	if in != r1.String() {
172		t.Errorf("New(%v) = %v, expect %v", in, r1.String(), in)
173	}
174
175	if r1.HasFragmentOnly != false {
176		t.Errorf("New(%v)::HasFragmentOnly %v expect %v", in, r1.HasFragmentOnly, false)
177	}
178
179	if r1.HasFullURL != false {
180		t.Errorf("New(%v)::HasFullURL %v expect %v", in, r1.HasFullURL, false)
181	}
182
183	if r1.HasURLPathOnly != true {
184		t.Errorf("New(%v)::HasURLPathOnly %v expect %v", in, r1.HasURLPathOnly, true)
185	}
186
187	if r1.HasFileScheme != false {
188		t.Errorf("New(%v)::HasFileScheme %v expect %v", in, r1.HasFileScheme, false)
189	}
190
191	if r1.GetPointer().String() != "" {
192		t.Errorf("New(%v)::GetPointer() %v expect %v", in, r1.GetPointer().String(), "")
193	}
194}
195
196// nolint: dupl
197func TestURLRelativePathOnly(t *testing.T) {
198
199	in := "document.json"
200
201	r1, err := New(in)
202	if err != nil {
203		t.Errorf("New(%v) error %s", in, err.Error())
204	}
205
206	if in != r1.String() {
207		t.Errorf("New(%v) = %v, expect %v", in, r1.String(), in)
208	}
209
210	if r1.HasFragmentOnly != false {
211		t.Errorf("New(%v)::HasFragmentOnly %v expect %v", in, r1.HasFragmentOnly, false)
212	}
213
214	if r1.HasFullURL != false {
215		t.Errorf("New(%v)::HasFullURL %v expect %v", in, r1.HasFullURL, false)
216	}
217
218	if r1.HasURLPathOnly != true {
219		t.Errorf("New(%v)::HasURLPathOnly %v expect %v", in, r1.HasURLPathOnly, true)
220	}
221
222	if r1.HasFileScheme != false {
223		t.Errorf("New(%v)::HasFileScheme %v expect %v", in, r1.HasFileScheme, false)
224	}
225
226	if r1.GetPointer().String() != "" {
227		t.Errorf("New(%v)::GetPointer() %v expect %v", in, r1.GetPointer().String(), "")
228	}
229}
230
231func TestInheritsInValid(t *testing.T) {
232	in1 := "http://www.test.com/doc.json"
233	in2 := "#/a/b"
234
235	r1, _ := New(in1)
236	r2 := Ref{}
237	result, err := r1.Inherits(r2)
238	assert.Error(t, err)
239	assert.Nil(t, result)
240
241	r1 = Ref{}
242	r2, _ = New(in2)
243	result, err = r1.Inherits(r2)
244	assert.NoError(t, err)
245	assert.Equal(t, r2, *result)
246}
247
248func TestInheritsValid(t *testing.T) {
249
250	in1 := "http://www.test.com/doc.json"
251	in2 := "#/a/b"
252	out := in1 + in2
253
254	r1, _ := New(in1)
255	r2, _ := New(in2)
256
257	result, err := r1.Inherits(r2)
258	if err != nil {
259		t.Errorf("Inherits(%s,%s) error %s", r1.String(), r2.String(), err.Error())
260	}
261
262	if result.String() != out {
263		t.Errorf("Inherits(%s,%s) = %s, expect %s", r1.String(), r2.String(), result.String(), out)
264	}
265
266	if result.GetPointer().String() != "/a/b" {
267		t.Errorf("result(%v)::GetPointer() %v expect %v", result.String(), result.GetPointer().String(), "/a/b")
268	}
269}
270
271func TestInheritsDifferentHost(t *testing.T) {
272
273	in1 := "http://www.test.com/doc.json"
274	in2 := "http://www.test2.com/doc.json#bla"
275
276	r1, _ := New(in1)
277	r2, _ := New(in2)
278
279	result, err := r1.Inherits(r2)
280
281	if err != nil {
282		t.Errorf("Inherits(%s,%s) should not fail. Error: %s", r1.String(), r2.String(), err.Error())
283	}
284
285	if result.String() != in2 {
286		t.Errorf("Inherits(%s,%s) should be %s but is %s", in1, in2, in2, result)
287	}
288
289	if result.GetPointer().String() != "" {
290		t.Errorf("result(%v)::GetPointer() %v expect %v", result.String(), result.GetPointer().String(), "")
291	}
292}
293
294func TestFileScheme(t *testing.T) {
295
296	in1 := "file:///Users/mac/1.json#a"
297	in2 := "file:///Users/mac/2.json#b"
298
299	r1, _ := New(in1)
300	r2, _ := New(in2)
301
302	if r1.HasFragmentOnly != false {
303		t.Errorf("New(%v)::HasFragmentOnly %v expect %v", in1, r1.HasFragmentOnly, false)
304	}
305
306	if r1.HasFileScheme != true {
307		t.Errorf("New(%v)::HasFileScheme %v expect %v", in1, r1.HasFileScheme, true)
308	}
309
310	if r1.HasFullFilePath != true {
311		t.Errorf("New(%v)::HasFullFilePath %v expect %v", in1, r1.HasFullFilePath, true)
312	}
313
314	if r1.IsCanonical() != true {
315		t.Errorf("New(%v)::IsCanonical %v expect %v", in1, r1.IsCanonical(), true)
316	}
317
318	result, err := r1.Inherits(r2)
319	if err != nil {
320		t.Errorf("Inherits(%s,%s) should not fail. Error: %s", r1.String(), r2.String(), err.Error())
321	}
322	if result.String() != in2 {
323		t.Errorf("Inherits(%s,%s) should be %s but is %s", in1, in2, in2, result)
324	}
325
326	if result.GetPointer().String() != "" {
327		t.Errorf("result(%v)::GetPointer() %v expect %v", result.String(), result.GetPointer().String(), "")
328	}
329}
330
331func TestReferenceResolution(t *testing.T) {
332
333	// 5.4. Reference Resolution Examples
334	// http://tools.ietf.org/html/rfc3986#section-5.4
335
336	base := "http://a/b/c/d;p?q"
337	baseRef, err := New(base)
338
339	if err != nil {
340		t.Errorf("New(%s) failed error: %s", base, err.Error())
341	}
342	if baseRef.String() != base {
343		t.Errorf("New(%s) %s expected %s", base, baseRef.String(), base)
344	}
345
346	checks := []string{
347		// 5.4.1. Normal Examples
348		// http://tools.ietf.org/html/rfc3986#section-5.4.1
349
350		"g:h", "g:h",
351		"g", "http://a/b/c/g",
352		"./g", "http://a/b/c/g",
353		"g/", "http://a/b/c/g/",
354		"/g", "http://a/g",
355		"//g", "http://g",
356		"?y", "http://a/b/c/d;p?y",
357		"g?y", "http://a/b/c/g?y",
358		"#s", "http://a/b/c/d;p?q#s",
359		"g#s", "http://a/b/c/g#s",
360		"g?y#s", "http://a/b/c/g?y#s",
361		";x", "http://a/b/c/;x",
362		"g;x", "http://a/b/c/g;x",
363		"g;x?y#s", "http://a/b/c/g;x?y#s",
364		"", "http://a/b/c/d;p?q",
365		".", "http://a/b/c/",
366		"./", "http://a/b/c/",
367		"..", "http://a/b/",
368		"../", "http://a/b/",
369		"../g", "http://a/b/g",
370		"../..", "http://a/",
371		"../../", "http://a/",
372		"../../g", "http://a/g",
373
374		// 5.4.2. Abnormal Examples
375		// http://tools.ietf.org/html/rfc3986#section-5.4.2
376
377		"../../../g", "http://a/g",
378		"../../../../g", "http://a/g",
379
380		"/./g", "http://a/g",
381		"/../g", "http://a/g",
382		"g.", "http://a/b/c/g.",
383		".g", "http://a/b/c/.g",
384		"g..", "http://a/b/c/g..",
385		"..g", "http://a/b/c/..g",
386
387		"./../g", "http://a/b/g",
388		"./g/.", "http://a/b/c/g/",
389		"g/./h", "http://a/b/c/g/h",
390		"g/../h", "http://a/b/c/h",
391		"g;x=1/./y", "http://a/b/c/g;x=1/y",
392		"g;x=1/../y", "http://a/b/c/y",
393
394		"g?y/./x", "http://a/b/c/g?y/./x",
395		"g?y/../x", "http://a/b/c/g?y/../x",
396		"g#s/./x", "http://a/b/c/g#s/./x",
397		"g#s/../x", "http://a/b/c/g#s/../x",
398
399		"http:g", "http:g", // for strict parsers
400		// "http:g", "http://a/b/c/g", // for backward compatibility
401
402	}
403	for i := 0; i < len(checks); i += 2 {
404		child := checks[i]
405		expected := checks[i+1]
406
407		childRef, e := New(child)
408		if e != nil {
409			t.Errorf("%d: New(%s) failed error: %s", i/2, child, e.Error())
410		}
411
412		res, e := baseRef.Inherits(childRef)
413		if res == nil {
414			t.Errorf("%d: Inherits(%s, %s) nil not expected", i/2, base, child)
415		}
416		if e != nil {
417			t.Errorf("%d: Inherits(%s) failed error: %s", i/2, child, e.Error())
418		}
419		if res.String() != expected {
420			t.Errorf("%d: Inherits(%s, %s) %s expected %s", i/2, base, child, res.String(), expected)
421		}
422	}
423}
424