github.com/apptainer/singularity@v3.1.1+incompatible/pkg/client/library/pull_test.go (about) 1 // Copyright (c) 2018, Sylabs Inc. All rights reserved. 2 // This software is licensed under a 3-clause BSD license. Please consult the 3 // LICENSE.md file distributed with the sources of this project regarding your 4 // rights to use or distribute this software. 5 6 package client 7 8 import ( 9 "bufio" 10 "bytes" 11 "io" 12 "io/ioutil" 13 "net/http" 14 "net/http/httptest" 15 "os" 16 "testing" 17 18 "github.com/sylabs/singularity/internal/pkg/sylog" 19 "github.com/sylabs/singularity/internal/pkg/test" 20 ) 21 22 type mockRawService struct { 23 t *testing.T 24 code int 25 testFile string 26 reqCallback func(*http.Request, *testing.T) 27 httpAddr string 28 httpPath string 29 httpServer *httptest.Server 30 baseURI string 31 } 32 33 func (m *mockRawService) Run() { 34 mux := http.NewServeMux() 35 mux.HandleFunc(m.httpPath, m.ServeHTTP) 36 m.httpServer = httptest.NewServer(mux) 37 m.httpAddr = m.httpServer.Listener.Addr().String() 38 m.baseURI = "http://" + m.httpAddr 39 } 40 41 func (m *mockRawService) Stop() { 42 m.httpServer.Close() 43 } 44 45 func (m *mockRawService) ServeHTTP(w http.ResponseWriter, r *http.Request) { 46 47 if m.reqCallback != nil { 48 m.reqCallback(r, m.t) 49 } 50 w.WriteHeader(m.code) 51 inFile, err := os.Open(m.testFile) 52 if err != nil { 53 m.t.Errorf("error opening file %v:", err) 54 } 55 defer inFile.Close() 56 57 _, err = io.Copy(w, bufio.NewReader(inFile)) 58 if err != nil { 59 sylog.Fatalf("Test HTTP server unable to output file: %v", err) 60 } 61 62 } 63 64 func Test_DownloadImage(t *testing.T) { 65 66 f, err := ioutil.TempFile("", "test") 67 if err != nil { 68 t.Fatalf("Error creating a temporary file for testing") 69 } 70 tempFile := f.Name() 71 f.Close() 72 os.Remove(tempFile) 73 74 tests := []struct { 75 name string 76 libraryRef string 77 outFile string 78 force bool 79 code int 80 testFile string 81 tokenFile string 82 checkContent bool 83 expectError bool 84 }{ 85 {"Bad filename", "entity/collection/image:tag", "notadir/test.sif", false, http.StatusBadRequest, "test_data/test_sha256", "test_data/test_token", false, true}, 86 {"Bad library ref", "entity/collection/im,age:tag", tempFile, false, http.StatusBadRequest, "test_data/test_sha256", "test_data/test_token", false, true}, 87 {"Server error", "entity/collection/image:tag", tempFile, false, http.StatusInternalServerError, "test_data/test_sha256", "test_data/test_token", false, true}, 88 {"Good Download", "entity/collection/image:tag", tempFile, false, http.StatusOK, "test_data/test_sha256", "test_data/test_token", true, false}, 89 {"Should not overwrite", "entity/collection/image:tag", tempFile, false, http.StatusOK, "test_data/test_sha256", "test_data/test_token", true, true}, 90 } 91 for _, tt := range tests { 92 t.Run(tt.name, test.WithoutPrivilege(func(t *testing.T) { 93 94 m := mockRawService{ 95 t: t, 96 code: tt.code, 97 testFile: tt.testFile, 98 httpPath: "/v1/imagefile/" + tt.libraryRef, 99 } 100 101 m.Run() 102 defer m.Stop() 103 104 err := DownloadImage(tt.outFile, tt.libraryRef, m.baseURI, tt.force, tt.tokenFile) 105 106 if err != nil && !tt.expectError { 107 t.Errorf("Unexpected error: %v", err) 108 } 109 if err == nil && tt.expectError { 110 t.Errorf("Unexpected success. Expected error.") 111 } 112 113 if tt.checkContent { 114 fileContent, err := ioutil.ReadFile(tt.outFile) 115 if err != nil { 116 t.Errorf("Error reading test output file: %v", err) 117 } 118 testContent, err := ioutil.ReadFile(tt.testFile) 119 if err != nil { 120 t.Errorf("Error reading test file: %v", err) 121 } 122 if !bytes.Equal(fileContent, testContent) { 123 t.Errorf("File contains '%v' - expected '%v'", fileContent, testContent) 124 } 125 } 126 127 })) 128 } 129 }