11package storage
22
33import (
4+ "bytes"
45 "context"
56 "errors"
67 "fmt"
@@ -15,7 +16,10 @@ import (
1516 "testing"
1617 "testing/fstest"
1718
19+ "github.com/stretchr/testify/assert"
1820 "github.com/stretchr/testify/require"
21+
22+ "github.com/operator-framework/operator-registry/alpha/declcfg"
1923)
2024
2125const urlPrefix = "/catalogs/"
@@ -170,14 +174,10 @@ func TestLocalDirStoraget(t *testing.T) {
170174
171175func TestLocalDirServerHandler (t * testing.T ) {
172176 store := & LocalDirV1 {RootDir : t .TempDir (), RootURL : & url.URL {Path : urlPrefix }}
173- testFS := fstest.MapFS {
174- "meta.json" : & fstest.MapFile {
175- Data : []byte (`{"foo":"bar"}` ),
176- },
177- }
178- if store .Store (context .Background (), "test-catalog" , testFS ) != nil {
177+ if store .Store (context .Background (), "test-catalog" , createTestFS (t )) != nil {
179178 t .Fatal ("failed to store test catalog and start server" )
180179 }
180+
181181 testServer := httptest .NewServer (store .StorageServerHandler ())
182182 defer testServer .Close ()
183183
@@ -242,10 +242,12 @@ func TestLocalDirServerHandler(t *testing.T) {
242242 URLPath : "/catalogs/non-existent-catalog/api/v1/all" ,
243243 },
244244 {
245- name : "Server returns 200 when path '/catalogs/<catalog>/api/v1/all' is queried, when catalog exists" ,
245+ name : "Server returns 200 with json-lines payload when path '/catalogs/<catalog>/api/v1/all' is queried, when catalog exists" ,
246246 expectedStatusCode : http .StatusOK ,
247- expectedContent : `{"foo":"bar"}` ,
248- URLPath : "/catalogs/test-catalog/api/v1/all" ,
247+ expectedContent : `{"image":"quaydock.io/namespace/bundle:0.0.3","name":"bundle.v0.0.1","package":"webhook_operator_test","properties":[{"type":"olm.bundle.object","value":{"data":"dW5pbXBvcnRhbnQK"}},{"type":"some.other","value":{"data":"arbitrary-info"}}],"relatedImages":[{"image":"testimage:latest","name":"test"}],"schema":"olm.bundle"}` + "\n " +
248+ `{"defaultChannel":"preview_test","name":"webhook_operator_test","schema":"olm.package"}` + "\n " +
249+ `{"entries":[{"name":"bundle.v0.0.1"}],"name":"preview_test","package":"webhook_operator_test","schema":"olm.channel"}` ,
250+ URLPath : "/catalogs/test-catalog/api/v1/all" ,
249251 },
250252 } {
251253 t .Run (tc .name , func (t * testing.T ) {
@@ -256,11 +258,14 @@ func TestLocalDirServerHandler(t *testing.T) {
256258 require .NoError (t , err )
257259
258260 require .Equal (t , tc .expectedStatusCode , resp .StatusCode )
261+ if resp .StatusCode == http .StatusOK {
262+ assert .Equal (t , "application/jsonl" , resp .Header .Get ("Content-Type" ))
263+ }
259264
260- var actualContent []byte
261- actualContent , err = io .ReadAll (resp .Body )
265+ actualContent , err := io .ReadAll (resp .Body )
262266 require .NoError (t , err )
263- require .Equal (t , tc .expectedContent , strings .TrimSpace (string (actualContent )))
267+
268+ require .Equal (t , strings .TrimSpace (tc .expectedContent ), strings .TrimSpace (string (actualContent )))
264269 require .NoError (t , resp .Body .Close ())
265270 })
266271 }
@@ -329,7 +334,7 @@ func TestMetasEndpoint(t *testing.T) {
329334 expectedContent : "" ,
330335 },
331336 {
332- name : "valid query with packageName that returns multiple blobs" ,
337+ name : "valid query with packageName that returns multiple blobs in json-lines format " ,
333338 queryParams : "?package=webhook_operator_test" ,
334339 expectedStatusCode : http .StatusOK ,
335340 expectedContent : `{"image":"quaydock.io/namespace/bundle:0.0.3","name":"bundle.v0.0.1","package":"webhook_operator_test","properties":[{"type":"olm.bundle.object","value":{"data":"dW5pbXBvcnRhbnQK"}},{"type":"some.other","value":{"data":"arbitrary-info"}}],"relatedImages":[{"image":"testimage:latest","name":"test"}],"schema":"olm.bundle"}
@@ -377,6 +382,9 @@ func TestMetasEndpoint(t *testing.T) {
377382 defer resp .Body .Close ()
378383
379384 require .Equal (t , tc .expectedStatusCode , resp .StatusCode )
385+ if resp .StatusCode == http .StatusOK {
386+ assert .Equal (t , "application/jsonl" , resp .Header .Get ("Content-Type" ))
387+ }
380388
381389 actualContent , err := io .ReadAll (resp .Body )
382390 require .NoError (t , err )
@@ -591,8 +599,38 @@ entries:
591599 testBundle := fmt .Sprintf (testBundleTemplate , testBundleImage , testBundleName , testPackageName , testBundleRelatedImageName , testBundleRelatedImageImage , testBundleObjectData )
592600 testChannel := fmt .Sprintf (testChannelTemplate , testPackageName , testChannelName , testBundleName )
593601 return & fstest.MapFS {
594- "bundle.yaml" : {Data : []byte (testBundle ), Mode : os .ModePerm },
595- "package.yaml" : {Data : []byte (testPackage ), Mode : os .ModePerm },
596- "channel.yaml" : {Data : []byte (testChannel ), Mode : os .ModePerm },
602+ "test-catalog.yaml" : {Data : []byte (
603+ generateJSONLinesOrFail (t , []byte (testBundle )) +
604+ generateJSONLinesOrFail (t , []byte (testPackage )) +
605+ generateJSONLinesOrFail (t , []byte (testChannel ))),
606+ Mode : os .ModePerm },
597607 }
598608}
609+
610+ // generateJSONLinesOrFail takes a byte slice of concatenated JSON objects and returns a JSONlines-formatted string
611+ // or raises a test failure in case of encountering any internal errors
612+ func generateJSONLinesOrFail (t * testing.T , in []byte ) string {
613+ var out strings.Builder
614+ reader := bytes .NewReader (in )
615+
616+ err := declcfg .WalkMetasReader (reader , func (meta * declcfg.Meta , err error ) error {
617+ if err != nil {
618+ return err
619+ }
620+
621+ if meta != nil && meta .Blob != nil {
622+ if meta .Blob [len (meta .Blob )- 1 ] != '\n' {
623+ return fmt .Errorf ("blob does not end with newline" )
624+ }
625+ }
626+
627+ _ , err = out .Write (meta .Blob )
628+ if err != nil {
629+ return err
630+ }
631+ return nil
632+ })
633+ require .NoError (t , err )
634+
635+ return out .String ()
636+ }
0 commit comments