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  }