-
1
-
2
-
3
-
4
-
5
-
6
-
7
-
8
-
9
-
10
-
11
-
12
-
13
-
14
-
15
-
16
-
17
-
18
-
19
-
20
-
21
-
22
-
23
-
24
-
25
-
26
-
27
-
28
-
29
-
30
-
31
-
32
-
33
-
34
-
35
-
36
-
37
-
38
-
39
-
40
-
41
-
42
-
43
-
44
-
45
-
46
-
47
-
48
-
49
-
50
-
51
-
52
-
53
-
54
-
55
-
56
-
57
-
58
-
59
-
60
-
61
-
62
-
63
-
64
-
65
-
66
-
67
-
68
-
69
-
70
-
71
-
72
-
73
-
74
-
75
-
76
-
77
-
78
-
79
-
80
-
81
-
82
-
83
-
84
-
85
-
86
-
87
-
88
-
89
-
90
-
91
-
92
-
93
-
94
-
95
-
96
-
97
-
98
-
99
-
100
-
101
-
102
-
103
-
104
-
105
-
106
-
107
-
108
-
109
-
110
-
111
-
112
-
113
-
114
-
115
-
116
-
117
-
118
-
119
-
120
-
121
-
122
-
123
-
124
-
125
-
126
-
127
-
128
-
129
-
130
-
131
-
132
-
133
-
134
-
135
-
136
-
137
-
138
-
139
-
140
-
141
-
142
-
143
-
144
-
145
-
146
-
147
-
148
-
149
-
150
-
151
-
152
-
153
-
154
-
155
-
156
-
157
-
158
-
159
-
160
-
161
-
162
-
163
-
164
-
165
-
166
-
167
-
168
-
169
-
170
-
171
-
172
-
173
-
174
-
175
-
176
-
177
-
178
-
179
-
180
-
181
-
182
-
183
-
184
-
185
-
186
-
187
-
188
-
189
-
190
-
191
-
192
-
193
-
194
-
195
-
196
-
197
-
198
-
199
-
200
-
201
-
202
-
203
-
204
-
205
-
206
-
207
-
208
-
209
-
210
-
211
-
212
-
213
-
214
-
215
-
216
-
217
-
218
-
219
-
220
-
221
-
222
-
223
-
224
-
225
-
226
-
227
-
228
-
229
-
230
-
231
-
232
-
233
-
234
-
235
-
236
-
237
-
238
-
239
-
240
-
241
-
242
-
243
-
244
-
245
-
246
-
247
-
248
-
249
-
250
-
251
-
252
-
253
-
254
-
255
-
256
-
257
-
258
-
259
-
260
-
261
-
262
-
263
-
264
-
265
-
266
-
267
-
268
-
269
-
270
-
271
-
272
-
273
-
274
-
275
-
276
-
277
-
278
-
279
-
280
-
281
-
282
-
283
-
284
-
285
-
286
-
287
-
288
-
289
-
290
-
291
-
292
-
293
-
294
-
295
-
296
-
297
-
298
-
299
-
300
-
301
-
302
-
303
-
304
-
305
-
306
-
307
-
308
-
309
-
310
-
311
-
312
-
313
-
314
-
315
-
316
-
317
-
318
-
319
-
320
-
321
-
322
-
323
-
324
-
325
-
326
-
327
-
328
-
329
-
330
-
331
-
332
-
333
-
334
-
335
-
336
-
337
-
338
-
339
-
340
-
341
-
342
-
343
-
344
-
345
-
346
-
347
-
348
-
349
-
350
-
351
-
352
-
353
-
354
-
355
-
356
-
357
-
358
-
359
-
360
-
361
-
362
-
363
-
364
-
365
-
366
-
367
-
368
-
369
-
370
-
371
-
372
-
373
-
374
-
375
-
376
-
377
-
378
-
379
-
380
-
381
-
382
-
383
-
384
-
385
-
386
-
387
-
388
-
389
-
390
-
391
-
392
-
393
-
394
-
395
-
396
-
397
-
398
-
399
-
400
-
401
-
402
-
403
-
404
-
405
-
406
-
407
-
408
-
409
-
410
-
411
-
412
-
413
-
414
-
415
-
416
-
417
-
418
-
419
-
420
-
421
-
422
-
423
-
424
-
425
-
426
-
427
-
428
-
429
-
430
-
431
-
432
-
433
-
434
-
435
-
436
-
437
-
438
-
439
-
440
-
441
-
442
-
443
-
444
-
445
-
446
-
447
-
448
-
449
-
450
-
451
-
452
-
453
-
454
-
455
-
456
-
457
-
458
-
459
-
460
-
461
-
462
-
463
-
464
-
465
-
466
-
467
-
468
-
469
-
470
-
471
-
472
-
473
-
474
-
475
-
476
-
477
-
478
-
479
-
480
-
481
-
482
-
483
-
484
-
485
-
486
-
487
-
488
-
489
-
490
-
491
-
492
-
493
-
494
-
495
-
496
-
497
-
498
-
499
-
500
-
501
-
502
-
503
-
504
-
505
-
506
-
507
-
508
-
509
-
510
-
511
-
512
-
513
-
514
-
515
-
516
-
517
-
518
-
519
-
520
-
521
-
522
-
523
-
524
-
525
-
526
-
527
-
528
-
529
-
530
-
531
-
532
-
533
-
534
-
535
-
536
-
537
-
538
-
539
-
540
-
541
-
542
-
543
-
544
-
545
-
546
-
547
-
548
-
549
-
550
-
551
-
552
-
553
-
554
-
555
-
556
-
557
-
558
-
559
-
560
-
561
-
562
-
563
-
564
-
565
-
566
-
567
-
568
-
569
-
570
-
571
-
572
-
573
-
574
-
575
-
576
-
577
-
578
-
579
-
580
-
581
-
582
-
583
-
584
-
585
-
586
-
587
-
588
-
589
-
590
-
591
-
592
-
593
-
594
-
595
-
596
-
597
-
598
-
599
-
600
-
601
-
602
-
603
-
604
-
605
-
606
-
607
-
608
-
609
-
610
-
611
-
612
-
613
-
614
-
615
-
616
-
617
-
618
-
619
-
620
-
621
-
622
-
623
-
624
-
625
-
626
-
627
-
628
-
629
-
630
-
631
-
632
-
633
-
634
-
635
-
636
-
637
-
638
-
639
-
640
-
641
-
642
-
643
-
644
-
645
-
646
-
647
-
648
-
649
-
650
-
651
-
652
-
653
-
654
-
655
-
656
-
657
-
658
-
659
-
660
-
661
-
662
-
663
-
664
-
665
-
666
-
667
-
668
-
669
-
670
-
671
-
672
-
673
-
674
-
675
-
676
-
677
-
678
-
679
-
680
-
681
-
682
-
683
-
684
-
685
-
686
-
687
-
688
-
689
-
690
-
691
-
692
-
693
-
694
-
695
-
696
-
697
-
698
-
699
-
700
-
701
-
702
-
703
-
704
-
705
-
706
-
707
-
708
-
709
-
710
-
711
-
712
-
713
-
714
-
715
-
716
-
717
-
718
-
719
-
720
-
721
-
722
-
723
-
724
// Copyright 2022 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package integration
import (
"fmt"
"net/http"
stdurl "net/url"
"strings"
"testing"
"time"
"code.gitea.io/gitea/models/db"
"code.gitea.io/gitea/models/packages"
conan_model "code.gitea.io/gitea/models/packages/conan"
"code.gitea.io/gitea/models/unittest"
user_model "code.gitea.io/gitea/models/user"
conan_module "code.gitea.io/gitea/modules/packages/conan"
"code.gitea.io/gitea/modules/setting"
conan_router "code.gitea.io/gitea/routers/api/packages/conan"
"code.gitea.io/gitea/tests"
"github.com/stretchr/testify/assert"
)
const (
conanfileName = "conanfile.py"
conaninfoName = "conaninfo.txt"
conanLicense = "MIT"
conanAuthor = "Gitea <info@gitea.io>"
conanHomepage = "https://gitea.io/"
conanURL = "https://gitea.com/"
conanDescription = "Description of ConanPackage"
conanTopic = "gitea"
conanPackageReference = "dummyreference"
contentConaninfo = `[settings]
arch=x84_64
[requires]
fmt/7.1.3
[options]
shared=False
[full_settings]
arch=x84_64
[full_requires]
fmt/7.1.3
[full_options]
shared=False
[recipe_hash]
74714915a51073acb548ca1ce29afbac
[env]
CC=gcc-10`
)
func addTokenAuthHeader(request *http.Request, token string) *http.Request {
request.Header.Set("Authorization", token)
return request
}
func buildConanfileContent(name, version string) string {
return `from conans import ConanFile, CMake, tools
class ConanPackageConan(ConanFile):
name = "` + name + `"
version = "` + version + `"
license = "` + conanLicense + `"
author = "` + conanAuthor + `"
homepage = "` + conanHomepage + `"
url = "` + conanURL + `"
description = "` + conanDescription + `"
topics = ("` + conanTopic + `")
settings = "os", "compiler", "build_type", "arch"
options = {"shared": [True, False], "fPIC": [True, False]}
default_options = {"shared": False, "fPIC": True}
generators = "cmake"`
}
func uploadConanPackageV1(t *testing.T, baseURL, token, name, version, user, channel string) {
contentConanfile := buildConanfileContent(name, version)
recipeURL := fmt.Sprintf("%s/v1/conans/%s/%s/%s/%s", baseURL, name, version, user, channel)
req := NewRequest(t, "GET", recipeURL)
req = addTokenAuthHeader(req, token)
MakeRequest(t, req, http.StatusNotFound)
req = NewRequest(t, "GET", fmt.Sprintf("%s/digest", recipeURL))
req = addTokenAuthHeader(req, token)
MakeRequest(t, req, http.StatusNotFound)
req = NewRequest(t, "GET", fmt.Sprintf("%s/download_urls", recipeURL))
req = addTokenAuthHeader(req, token)
MakeRequest(t, req, http.StatusNotFound)
req = NewRequest(t, "POST", fmt.Sprintf("%s/upload_urls", recipeURL))
MakeRequest(t, req, http.StatusUnauthorized)
req = NewRequestWithJSON(t, "POST", fmt.Sprintf("%s/upload_urls", recipeURL), map[string]int64{
conanfileName: int64(len(contentConanfile)),
"removed.txt": 0,
})
req = addTokenAuthHeader(req, token)
resp := MakeRequest(t, req, http.StatusOK)
uploadURLs := make(map[string]string)
DecodeJSON(t, resp, &uploadURLs)
assert.Contains(t, uploadURLs, conanfileName)
assert.NotContains(t, uploadURLs, "removed.txt")
uploadURL := uploadURLs[conanfileName]
assert.NotEmpty(t, uploadURL)
req = NewRequestWithBody(t, "PUT", uploadURL, strings.NewReader(contentConanfile))
req = addTokenAuthHeader(req, token)
MakeRequest(t, req, http.StatusCreated)
packageURL := fmt.Sprintf("%s/packages/%s", recipeURL, conanPackageReference)
req = NewRequest(t, "GET", packageURL)
req = addTokenAuthHeader(req, token)
MakeRequest(t, req, http.StatusNotFound)
req = NewRequest(t, "GET", fmt.Sprintf("%s/digest", packageURL))
req = addTokenAuthHeader(req, token)
MakeRequest(t, req, http.StatusNotFound)
req = NewRequest(t, "GET", fmt.Sprintf("%s/download_urls", packageURL))
req = addTokenAuthHeader(req, token)
MakeRequest(t, req, http.StatusNotFound)
req = NewRequest(t, "POST", fmt.Sprintf("%s/upload_urls", packageURL))
MakeRequest(t, req, http.StatusUnauthorized)
req = NewRequestWithJSON(t, "POST", fmt.Sprintf("%s/upload_urls", packageURL), map[string]int64{
conaninfoName: int64(len(contentConaninfo)),
"removed.txt": 0,
})
req = addTokenAuthHeader(req, token)
resp = MakeRequest(t, req, http.StatusOK)
uploadURLs = make(map[string]string)
DecodeJSON(t, resp, &uploadURLs)
assert.Contains(t, uploadURLs, conaninfoName)
assert.NotContains(t, uploadURLs, "removed.txt")
uploadURL = uploadURLs[conaninfoName]
assert.NotEmpty(t, uploadURL)
req = NewRequestWithBody(t, "PUT", uploadURL, strings.NewReader(contentConaninfo))
req = addTokenAuthHeader(req, token)
MakeRequest(t, req, http.StatusCreated)
}
func uploadConanPackageV2(t *testing.T, baseURL, token, name, version, user, channel, recipeRevision, packageRevision string) {
contentConanfile := buildConanfileContent(name, version)
recipeURL := fmt.Sprintf("%s/v2/conans/%s/%s/%s/%s/revisions/%s", baseURL, name, version, user, channel, recipeRevision)
req := NewRequestWithBody(t, "PUT", fmt.Sprintf("%s/files/%s", recipeURL, conanfileName), strings.NewReader(contentConanfile))
req = addTokenAuthHeader(req, token)
MakeRequest(t, req, http.StatusCreated)
req = NewRequest(t, "GET", fmt.Sprintf("%s/files", recipeURL))
req = addTokenAuthHeader(req, token)
resp := MakeRequest(t, req, http.StatusOK)
var list *struct {
Files map[string]interface{} `json:"files"`
}
DecodeJSON(t, resp, &list)
assert.Len(t, list.Files, 1)
assert.Contains(t, list.Files, conanfileName)
packageURL := fmt.Sprintf("%s/packages/%s/revisions/%s", recipeURL, conanPackageReference, packageRevision)
req = NewRequest(t, "GET", fmt.Sprintf("%s/files", packageURL))
req = addTokenAuthHeader(req, token)
MakeRequest(t, req, http.StatusNotFound)
req = NewRequestWithBody(t, "PUT", fmt.Sprintf("%s/files/%s", packageURL, conaninfoName), strings.NewReader(contentConaninfo))
req = addTokenAuthHeader(req, token)
MakeRequest(t, req, http.StatusCreated)
req = NewRequest(t, "GET", fmt.Sprintf("%s/files", packageURL))
req = addTokenAuthHeader(req, token)
resp = MakeRequest(t, req, http.StatusOK)
list = nil
DecodeJSON(t, resp, &list)
assert.Len(t, list.Files, 1)
assert.Contains(t, list.Files, conaninfoName)
}
func TestPackageConan(t *testing.T) {
defer tests.PrepareTestEnv(t)()
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
name := "ConanPackage"
version1 := "1.2"
version2 := "1.3"
user1 := "dummy"
user2 := "gitea"
channel1 := "test"
channel2 := "final"
revision1 := "rev1"
revision2 := "rev2"
url := fmt.Sprintf("%sapi/packages/%s/conan", setting.AppURL, user.Name)
t.Run("v1", func(t *testing.T) {
t.Run("Ping", func(t *testing.T) {
defer tests.PrintCurrentTest(t)()
req := NewRequest(t, "GET", fmt.Sprintf("%s/v1/ping", url))
resp := MakeRequest(t, req, http.StatusOK)
assert.Equal(t, "revisions", resp.Header().Get("X-Conan-Server-Capabilities"))
})
token := ""
t.Run("Authenticate", func(t *testing.T) {
defer tests.PrintCurrentTest(t)()
req := NewRequest(t, "GET", fmt.Sprintf("%s/v1/users/authenticate", url))
req = AddBasicAuthHeader(req, user.Name)
resp := MakeRequest(t, req, http.StatusOK)
body := resp.Body.String()
assert.NotEmpty(t, body)
token = fmt.Sprintf("Bearer %s", body)
})
t.Run("CheckCredentials", func(t *testing.T) {
defer tests.PrintCurrentTest(t)()
req := NewRequest(t, "GET", fmt.Sprintf("%s/v1/users/check_credentials", url))
req = addTokenAuthHeader(req, token)
MakeRequest(t, req, http.StatusOK)
})
t.Run("Upload", func(t *testing.T) {
defer tests.PrintCurrentTest(t)()
uploadConanPackageV1(t, url, token, name, version1, user1, channel1)
t.Run("Validate", func(t *testing.T) {
defer tests.PrintCurrentTest(t)()
pvs, err := packages.GetVersionsByPackageType(db.DefaultContext, user.ID, packages.TypeConan)
assert.NoError(t, err)
assert.Len(t, pvs, 1)
pd, err := packages.GetPackageDescriptor(db.DefaultContext, pvs[0])
assert.NoError(t, err)
assert.Nil(t, pd.SemVer)
assert.Equal(t, name, pd.Package.Name)
assert.Equal(t, version1, pd.Version.Version)
assert.IsType(t, &conan_module.Metadata{}, pd.Metadata)
metadata := pd.Metadata.(*conan_module.Metadata)
assert.Equal(t, conanLicense, metadata.License)
assert.Equal(t, conanAuthor, metadata.Author)
assert.Equal(t, conanHomepage, metadata.ProjectURL)
assert.Equal(t, conanURL, metadata.RepositoryURL)
assert.Equal(t, conanDescription, metadata.Description)
assert.Equal(t, []string{conanTopic}, metadata.Keywords)
pfs, err := packages.GetFilesByVersionID(db.DefaultContext, pvs[0].ID)
assert.NoError(t, err)
assert.Len(t, pfs, 2)
for _, pf := range pfs {
pb, err := packages.GetBlobByID(db.DefaultContext, pf.BlobID)
assert.NoError(t, err)
if pf.Name == conanfileName {
assert.True(t, pf.IsLead)
assert.Equal(t, int64(len(buildConanfileContent(name, version1))), pb.Size)
} else if pf.Name == conaninfoName {
assert.False(t, pf.IsLead)
assert.Equal(t, int64(len(contentConaninfo)), pb.Size)
} else {
assert.Fail(t, "unknown file: %s", pf.Name)
}
}
})
})
t.Run("Download", func(t *testing.T) {
defer tests.PrintCurrentTest(t)()
recipeURL := fmt.Sprintf("%s/v1/conans/%s/%s/%s/%s", url, name, version1, user1, channel1)
req := NewRequest(t, "GET", recipeURL)
resp := MakeRequest(t, req, http.StatusOK)
fileHashes := make(map[string]string)
DecodeJSON(t, resp, &fileHashes)
assert.Len(t, fileHashes, 1)
assert.Contains(t, fileHashes, conanfileName)
assert.Equal(t, "7abc52241c22090782c54731371847a8", fileHashes[conanfileName])
req = NewRequest(t, "GET", fmt.Sprintf("%s/digest", recipeURL))
resp = MakeRequest(t, req, http.StatusOK)
downloadURLs := make(map[string]string)
DecodeJSON(t, resp, &downloadURLs)
assert.Contains(t, downloadURLs, conanfileName)
req = NewRequest(t, "GET", fmt.Sprintf("%s/download_urls", recipeURL))
resp = MakeRequest(t, req, http.StatusOK)
DecodeJSON(t, resp, &downloadURLs)
assert.Contains(t, downloadURLs, conanfileName)
req = NewRequest(t, "GET", downloadURLs[conanfileName])
resp = MakeRequest(t, req, http.StatusOK)
assert.Equal(t, buildConanfileContent(name, version1), resp.Body.String())
packageURL := fmt.Sprintf("%s/packages/%s", recipeURL, conanPackageReference)
req = NewRequest(t, "GET", packageURL)
resp = MakeRequest(t, req, http.StatusOK)
fileHashes = make(map[string]string)
DecodeJSON(t, resp, &fileHashes)
assert.Len(t, fileHashes, 1)
assert.Contains(t, fileHashes, conaninfoName)
assert.Equal(t, "7628bfcc5b17f1470c468621a78df394", fileHashes[conaninfoName])
req = NewRequest(t, "GET", fmt.Sprintf("%s/digest", packageURL))
resp = MakeRequest(t, req, http.StatusOK)
downloadURLs = make(map[string]string)
DecodeJSON(t, resp, &downloadURLs)
assert.Contains(t, downloadURLs, conaninfoName)
req = NewRequest(t, "GET", fmt.Sprintf("%s/download_urls", packageURL))
resp = MakeRequest(t, req, http.StatusOK)
DecodeJSON(t, resp, &downloadURLs)
assert.Contains(t, downloadURLs, conaninfoName)
req = NewRequest(t, "GET", downloadURLs[conaninfoName])
resp = MakeRequest(t, req, http.StatusOK)
assert.Equal(t, contentConaninfo, resp.Body.String())
})
t.Run("Search", func(t *testing.T) {
uploadConanPackageV1(t, url, token, name, version2, user1, channel1)
uploadConanPackageV1(t, url, token, name, version1, user1, channel2)
uploadConanPackageV1(t, url, token, name, version1, user2, channel1)
uploadConanPackageV1(t, url, token, name, version1, user2, channel2)
t.Run("Recipe", func(t *testing.T) {
defer tests.PrintCurrentTest(t)()
cases := []struct {
Query string
Expected []string
}{
{"ConanPackage", []string{"ConanPackage/1.2@dummy/test", "ConanPackage/1.3@dummy/test", "ConanPackage/1.2@dummy/final", "ConanPackage/1.2@gitea/test", "ConanPackage/1.2@gitea/final"}},
{"ConanPackage/1.2", []string{"ConanPackage/1.2@dummy/test", "ConanPackage/1.2@dummy/final", "ConanPackage/1.2@gitea/test", "ConanPackage/1.2@gitea/final"}},
{"ConanPackage/1.1", []string{}},
{"Conan*", []string{"ConanPackage/1.2@dummy/test", "ConanPackage/1.3@dummy/test", "ConanPackage/1.2@dummy/final", "ConanPackage/1.2@gitea/test", "ConanPackage/1.2@gitea/final"}},
{"ConanPackage/", []string{"ConanPackage/1.2@dummy/test", "ConanPackage/1.3@dummy/test", "ConanPackage/1.2@dummy/final", "ConanPackage/1.2@gitea/test", "ConanPackage/1.2@gitea/final"}},
{"ConanPackage/*", []string{"ConanPackage/1.2@dummy/test", "ConanPackage/1.3@dummy/test", "ConanPackage/1.2@dummy/final", "ConanPackage/1.2@gitea/test", "ConanPackage/1.2@gitea/final"}},
{"ConanPackage/1*", []string{"ConanPackage/1.2@dummy/test", "ConanPackage/1.3@dummy/test", "ConanPackage/1.2@dummy/final", "ConanPackage/1.2@gitea/test", "ConanPackage/1.2@gitea/final"}},
{"ConanPackage/*2", []string{"ConanPackage/1.2@dummy/test", "ConanPackage/1.2@dummy/final", "ConanPackage/1.2@gitea/test", "ConanPackage/1.2@gitea/final"}},
{"ConanPackage/1*2", []string{"ConanPackage/1.2@dummy/test", "ConanPackage/1.2@dummy/final", "ConanPackage/1.2@gitea/test", "ConanPackage/1.2@gitea/final"}},
{"ConanPackage/1.2@", []string{"ConanPackage/1.2@dummy/test", "ConanPackage/1.2@dummy/final", "ConanPackage/1.2@gitea/test", "ConanPackage/1.2@gitea/final"}},
{"ConanPackage/1.2@du*", []string{"ConanPackage/1.2@dummy/test", "ConanPackage/1.2@dummy/final"}},
{"ConanPackage/1.2@du*/", []string{"ConanPackage/1.2@dummy/test", "ConanPackage/1.2@dummy/final"}},
{"ConanPackage/1.2@du*/*test", []string{"ConanPackage/1.2@dummy/test"}},
{"ConanPackage/1.2@du*/*st", []string{"ConanPackage/1.2@dummy/test"}},
{"ConanPackage/1.2@gitea/*", []string{"ConanPackage/1.2@gitea/test", "ConanPackage/1.2@gitea/final"}},
{"*/*@dummy", []string{"ConanPackage/1.2@dummy/test", "ConanPackage/1.3@dummy/test", "ConanPackage/1.2@dummy/final"}},
{"*/*@*/final", []string{"ConanPackage/1.2@dummy/final", "ConanPackage/1.2@gitea/final"}},
}
for i, c := range cases {
req := NewRequest(t, "GET", fmt.Sprintf("%s/v1/conans/search?q=%s", url, stdurl.QueryEscape(c.Query)))
resp := MakeRequest(t, req, http.StatusOK)
var result *conan_router.SearchResult
DecodeJSON(t, resp, &result)
assert.ElementsMatch(t, c.Expected, result.Results, "case %d: unexpected result", i)
}
})
t.Run("Package", func(t *testing.T) {
defer tests.PrintCurrentTest(t)()
req := NewRequest(t, "GET", fmt.Sprintf("%s/v1/conans/%s/%s/%s/%s/search", url, name, version1, user1, channel2))
resp := MakeRequest(t, req, http.StatusOK)
var result map[string]*conan_module.Conaninfo
DecodeJSON(t, resp, &result)
assert.Contains(t, result, conanPackageReference)
info := result[conanPackageReference]
assert.NotEmpty(t, info.Settings)
})
})
t.Run("Delete", func(t *testing.T) {
t.Run("Package", func(t *testing.T) {
defer tests.PrintCurrentTest(t)()
cases := []struct {
Channel string
References []string
}{
{channel1, []string{conanPackageReference}},
{channel2, []string{}},
}
for i, c := range cases {
rref, _ := conan_module.NewRecipeReference(name, version1, user1, c.Channel, conan_module.DefaultRevision)
references, err := conan_model.GetPackageReferences(db.DefaultContext, user.ID, rref)
assert.NoError(t, err)
assert.NotEmpty(t, references)
req := NewRequestWithJSON(t, "POST", fmt.Sprintf("%s/v1/conans/%s/%s/%s/%s/packages/delete", url, name, version1, user1, c.Channel), map[string][]string{
"package_ids": c.References,
})
req = addTokenAuthHeader(req, token)
MakeRequest(t, req, http.StatusOK)
references, err = conan_model.GetPackageReferences(db.DefaultContext, user.ID, rref)
assert.NoError(t, err)
assert.Empty(t, references, "case %d: should be empty", i)
}
})
t.Run("Recipe", func(t *testing.T) {
defer tests.PrintCurrentTest(t)()
cases := []struct {
Channel string
}{
{channel1},
{channel2},
}
for i, c := range cases {
rref, _ := conan_module.NewRecipeReference(name, version1, user1, c.Channel, conan_module.DefaultRevision)
revisions, err := conan_model.GetRecipeRevisions(db.DefaultContext, user.ID, rref)
assert.NoError(t, err)
assert.NotEmpty(t, revisions)
req := NewRequest(t, "DELETE", fmt.Sprintf("%s/v1/conans/%s/%s/%s/%s", url, name, version1, user1, c.Channel))
req = addTokenAuthHeader(req, token)
MakeRequest(t, req, http.StatusOK)
revisions, err = conan_model.GetRecipeRevisions(db.DefaultContext, user.ID, rref)
assert.NoError(t, err)
assert.Empty(t, revisions, "case %d: should be empty", i)
}
})
})
})
t.Run("v2", func(t *testing.T) {
t.Run("Ping", func(t *testing.T) {
defer tests.PrintCurrentTest(t)()
req := NewRequest(t, "GET", fmt.Sprintf("%s/v2/ping", url))
resp := MakeRequest(t, req, http.StatusOK)
assert.Equal(t, "revisions", resp.Header().Get("X-Conan-Server-Capabilities"))
})
token := ""
t.Run("Authenticate", func(t *testing.T) {
defer tests.PrintCurrentTest(t)()
req := NewRequest(t, "GET", fmt.Sprintf("%s/v2/users/authenticate", url))
req = AddBasicAuthHeader(req, user.Name)
resp := MakeRequest(t, req, http.StatusOK)
body := resp.Body.String()
assert.NotEmpty(t, body)
token = fmt.Sprintf("Bearer %s", body)
})
t.Run("CheckCredentials", func(t *testing.T) {
defer tests.PrintCurrentTest(t)()
req := NewRequest(t, "GET", fmt.Sprintf("%s/v2/users/check_credentials", url))
req = addTokenAuthHeader(req, token)
MakeRequest(t, req, http.StatusOK)
})
t.Run("Upload", func(t *testing.T) {
defer tests.PrintCurrentTest(t)()
uploadConanPackageV2(t, url, token, name, version1, user1, channel1, revision1, revision1)
t.Run("Validate", func(t *testing.T) {
defer tests.PrintCurrentTest(t)()
pvs, err := packages.GetVersionsByPackageType(db.DefaultContext, user.ID, packages.TypeConan)
assert.NoError(t, err)
assert.Len(t, pvs, 2)
})
})
t.Run("Latest", func(t *testing.T) {
defer tests.PrintCurrentTest(t)()
recipeURL := fmt.Sprintf("%s/v2/conans/%s/%s/%s/%s", url, name, version1, user1, channel1)
req := NewRequest(t, "GET", fmt.Sprintf("%s/latest", recipeURL))
resp := MakeRequest(t, req, http.StatusOK)
obj := make(map[string]string)
DecodeJSON(t, resp, &obj)
assert.Contains(t, obj, "revision")
assert.Equal(t, revision1, obj["revision"])
req = NewRequest(t, "GET", fmt.Sprintf("%s/revisions/%s/packages/%s/latest", recipeURL, revision1, conanPackageReference))
resp = MakeRequest(t, req, http.StatusOK)
obj = make(map[string]string)
DecodeJSON(t, resp, &obj)
assert.Contains(t, obj, "revision")
assert.Equal(t, revision1, obj["revision"])
})
t.Run("ListRevisions", func(t *testing.T) {
defer tests.PrintCurrentTest(t)()
uploadConanPackageV2(t, url, token, name, version1, user1, channel1, revision1, revision2)
uploadConanPackageV2(t, url, token, name, version1, user1, channel1, revision2, revision1)
uploadConanPackageV2(t, url, token, name, version1, user1, channel1, revision2, revision2)
recipeURL := fmt.Sprintf("%s/v2/conans/%s/%s/%s/%s/revisions", url, name, version1, user1, channel1)
req := NewRequest(t, "GET", recipeURL)
resp := MakeRequest(t, req, http.StatusOK)
type RevisionInfo struct {
Revision string `json:"revision"`
Time time.Time `json:"time"`
}
type RevisionList struct {
Revisions []*RevisionInfo `json:"revisions"`
}
var list *RevisionList
DecodeJSON(t, resp, &list)
assert.Len(t, list.Revisions, 2)
revs := make([]string, 0, len(list.Revisions))
for _, rev := range list.Revisions {
revs = append(revs, rev.Revision)
}
assert.ElementsMatch(t, []string{revision1, revision2}, revs)
req = NewRequest(t, "GET", fmt.Sprintf("%s/%s/packages/%s/revisions", recipeURL, revision1, conanPackageReference))
resp = MakeRequest(t, req, http.StatusOK)
DecodeJSON(t, resp, &list)
assert.Len(t, list.Revisions, 2)
revs = make([]string, 0, len(list.Revisions))
for _, rev := range list.Revisions {
revs = append(revs, rev.Revision)
}
assert.ElementsMatch(t, []string{revision1, revision2}, revs)
})
t.Run("Search", func(t *testing.T) {
t.Run("Recipe", func(t *testing.T) {
defer tests.PrintCurrentTest(t)()
cases := []struct {
Query string
Expected []string
}{
{"ConanPackage", []string{"ConanPackage/1.2@dummy/test", "ConanPackage/1.3@dummy/test", "ConanPackage/1.2@gitea/test", "ConanPackage/1.2@gitea/final"}},
{"ConanPackage/1.2", []string{"ConanPackage/1.2@dummy/test", "ConanPackage/1.2@gitea/test", "ConanPackage/1.2@gitea/final"}},
{"ConanPackage/1.1", []string{}},
{"Conan*", []string{"ConanPackage/1.2@dummy/test", "ConanPackage/1.3@dummy/test", "ConanPackage/1.2@gitea/test", "ConanPackage/1.2@gitea/final"}},
{"ConanPackage/", []string{"ConanPackage/1.2@dummy/test", "ConanPackage/1.3@dummy/test", "ConanPackage/1.2@gitea/test", "ConanPackage/1.2@gitea/final"}},
{"ConanPackage/*", []string{"ConanPackage/1.2@dummy/test", "ConanPackage/1.3@dummy/test", "ConanPackage/1.2@gitea/test", "ConanPackage/1.2@gitea/final"}},
{"ConanPackage/1*", []string{"ConanPackage/1.2@dummy/test", "ConanPackage/1.3@dummy/test", "ConanPackage/1.2@gitea/test", "ConanPackage/1.2@gitea/final"}},
{"ConanPackage/*2", []string{"ConanPackage/1.2@dummy/test", "ConanPackage/1.2@gitea/test", "ConanPackage/1.2@gitea/final"}},
{"ConanPackage/1*2", []string{"ConanPackage/1.2@dummy/test", "ConanPackage/1.2@gitea/test", "ConanPackage/1.2@gitea/final"}},
{"ConanPackage/1.2@", []string{"ConanPackage/1.2@dummy/test", "ConanPackage/1.2@gitea/test", "ConanPackage/1.2@gitea/final"}},
{"ConanPackage/1.2@du*", []string{"ConanPackage/1.2@dummy/test"}},
{"ConanPackage/1.2@du*/", []string{"ConanPackage/1.2@dummy/test"}},
{"ConanPackage/1.2@du*/*test", []string{"ConanPackage/1.2@dummy/test"}},
{"ConanPackage/1.2@du*/*st", []string{"ConanPackage/1.2@dummy/test"}},
{"ConanPackage/1.2@gitea/*", []string{"ConanPackage/1.2@gitea/test", "ConanPackage/1.2@gitea/final"}},
{"*/*@dummy", []string{"ConanPackage/1.2@dummy/test", "ConanPackage/1.3@dummy/test"}},
{"*/*@*/final", []string{"ConanPackage/1.2@gitea/final"}},
}
for i, c := range cases {
req := NewRequest(t, "GET", fmt.Sprintf("%s/v2/conans/search?q=%s", url, stdurl.QueryEscape(c.Query)))
resp := MakeRequest(t, req, http.StatusOK)
var result *conan_router.SearchResult
DecodeJSON(t, resp, &result)
assert.ElementsMatch(t, c.Expected, result.Results, "case %d: unexpected result", i)
}
})
t.Run("Package", func(t *testing.T) {
defer tests.PrintCurrentTest(t)()
req := NewRequest(t, "GET", fmt.Sprintf("%s/v2/conans/%s/%s/%s/%s/search", url, name, version1, user1, channel1))
resp := MakeRequest(t, req, http.StatusOK)
var result map[string]*conan_module.Conaninfo
DecodeJSON(t, resp, &result)
assert.Contains(t, result, conanPackageReference)
info := result[conanPackageReference]
assert.NotEmpty(t, info.Settings)
req = NewRequest(t, "GET", fmt.Sprintf("%s/v2/conans/%s/%s/%s/%s/revisions/%s/search", url, name, version1, user1, channel1, revision1))
resp = MakeRequest(t, req, http.StatusOK)
result = make(map[string]*conan_module.Conaninfo)
DecodeJSON(t, resp, &result)
assert.Contains(t, result, conanPackageReference)
info = result[conanPackageReference]
assert.NotEmpty(t, info.Settings)
})
})
t.Run("Delete", func(t *testing.T) {
t.Run("Package", func(t *testing.T) {
defer tests.PrintCurrentTest(t)()
rref, _ := conan_module.NewRecipeReference(name, version1, user1, channel1, revision1)
pref, _ := conan_module.NewPackageReference(rref, conanPackageReference, conan_module.DefaultRevision)
checkPackageRevisionCount := func(count int) {
revisions, err := conan_model.GetPackageRevisions(db.DefaultContext, user.ID, pref)
assert.NoError(t, err)
assert.Len(t, revisions, count)
}
checkPackageReferenceCount := func(count int) {
references, err := conan_model.GetPackageReferences(db.DefaultContext, user.ID, rref)
assert.NoError(t, err)
assert.Len(t, references, count)
}
checkPackageRevisionCount(2)
req := NewRequest(t, "DELETE", fmt.Sprintf("%s/v2/conans/%s/%s/%s/%s/revisions/%s/packages/%s/revisions/%s", url, name, version1, user1, channel1, revision1, conanPackageReference, revision1))
req = addTokenAuthHeader(req, token)
MakeRequest(t, req, http.StatusOK)
checkPackageRevisionCount(1)
req = NewRequest(t, "DELETE", fmt.Sprintf("%s/v2/conans/%s/%s/%s/%s/revisions/%s/packages/%s", url, name, version1, user1, channel1, revision1, conanPackageReference))
req = addTokenAuthHeader(req, token)
MakeRequest(t, req, http.StatusOK)
checkPackageRevisionCount(0)
rref = rref.WithRevision(revision2)
checkPackageReferenceCount(1)
req = NewRequest(t, "DELETE", fmt.Sprintf("%s/v2/conans/%s/%s/%s/%s/revisions/%s/packages", url, name, version1, user1, channel1, revision2))
req = addTokenAuthHeader(req, token)
MakeRequest(t, req, http.StatusOK)
checkPackageReferenceCount(0)
})
t.Run("Recipe", func(t *testing.T) {
defer tests.PrintCurrentTest(t)()
rref, _ := conan_module.NewRecipeReference(name, version1, user1, channel1, conan_module.DefaultRevision)
checkRecipeRevisionCount := func(count int) {
revisions, err := conan_model.GetRecipeRevisions(db.DefaultContext, user.ID, rref)
assert.NoError(t, err)
assert.Len(t, revisions, count)
}
checkRecipeRevisionCount(2)
req := NewRequest(t, "DELETE", fmt.Sprintf("%s/v2/conans/%s/%s/%s/%s/revisions/%s", url, name, version1, user1, channel1, revision1))
req = addTokenAuthHeader(req, token)
MakeRequest(t, req, http.StatusOK)
checkRecipeRevisionCount(1)
req = NewRequest(t, "DELETE", fmt.Sprintf("%s/v2/conans/%s/%s/%s/%s", url, name, version1, user1, channel1))
req = addTokenAuthHeader(req, token)
MakeRequest(t, req, http.StatusOK)
checkRecipeRevisionCount(0)
})
})
})
}