github.com/xhghs/rclone@v1.51.1-0.20200430155106-e186a28cced8/cmd/serve/http/http_test.go (about) 1 package http 2 3 import ( 4 "flag" 5 "io/ioutil" 6 "net/http" 7 "strings" 8 "testing" 9 "time" 10 11 _ "github.com/rclone/rclone/backend/local" 12 "github.com/rclone/rclone/cmd/serve/httplib" 13 "github.com/rclone/rclone/fs" 14 "github.com/rclone/rclone/fs/config" 15 "github.com/rclone/rclone/fs/filter" 16 "github.com/stretchr/testify/assert" 17 "github.com/stretchr/testify/require" 18 ) 19 20 var ( 21 updateGolden = flag.Bool("updategolden", false, "update golden files for regression test") 22 httpServer *server 23 testURL string 24 ) 25 26 const ( 27 testBindAddress = "localhost:0" 28 ) 29 30 func startServer(t *testing.T, f fs.Fs) { 31 opt := httplib.DefaultOpt 32 opt.ListenAddr = testBindAddress 33 httpServer = newServer(f, &opt) 34 assert.NoError(t, httpServer.Serve()) 35 testURL = httpServer.Server.URL() 36 37 // try to connect to the test server 38 pause := time.Millisecond 39 for i := 0; i < 10; i++ { 40 resp, err := http.Head(testURL) 41 if err == nil { 42 _ = resp.Body.Close() 43 return 44 } 45 // t.Logf("couldn't connect, sleeping for %v: %v", pause, err) 46 time.Sleep(pause) 47 pause *= 2 48 } 49 t.Fatal("couldn't connect to server") 50 51 } 52 53 func TestInit(t *testing.T) { 54 // Configure the remote 55 config.LoadConfig() 56 // fs.Config.LogLevel = fs.LogLevelDebug 57 // fs.Config.DumpHeaders = true 58 // fs.Config.DumpBodies = true 59 60 // exclude files called hidden.txt and directories called hidden 61 require.NoError(t, filter.Active.AddRule("- hidden.txt")) 62 require.NoError(t, filter.Active.AddRule("- hidden/**")) 63 64 // Create a test Fs 65 f, err := fs.NewFs("testdata/files") 66 require.NoError(t, err) 67 68 startServer(t, f) 69 } 70 71 // check body against the file, or re-write body if -updategolden is 72 // set. 73 func checkGolden(t *testing.T, fileName string, got []byte) { 74 if *updateGolden { 75 t.Logf("Updating golden file %q", fileName) 76 err := ioutil.WriteFile(fileName, got, 0666) 77 require.NoError(t, err) 78 } else { 79 want, err := ioutil.ReadFile(fileName) 80 require.NoError(t, err) 81 wants := strings.Split(string(want), "\n") 82 gots := strings.Split(string(got), "\n") 83 assert.Equal(t, wants, gots, fileName) 84 } 85 } 86 87 func TestGET(t *testing.T) { 88 for _, test := range []struct { 89 URL string 90 Status int 91 Golden string 92 Method string 93 Range string 94 }{ 95 { 96 URL: "", 97 Status: http.StatusOK, 98 Golden: "testdata/golden/index.html", 99 }, 100 { 101 URL: "notfound", 102 Status: http.StatusNotFound, 103 Golden: "testdata/golden/notfound.html", 104 }, 105 { 106 URL: "dirnotfound/", 107 Status: http.StatusNotFound, 108 Golden: "testdata/golden/dirnotfound.html", 109 }, 110 { 111 URL: "hidden/", 112 Status: http.StatusNotFound, 113 Golden: "testdata/golden/hiddendir.html", 114 }, 115 { 116 URL: "one%25.txt", 117 Status: http.StatusOK, 118 Golden: "testdata/golden/one.txt", 119 }, 120 { 121 URL: "hidden.txt", 122 Status: http.StatusNotFound, 123 Golden: "testdata/golden/hidden.txt", 124 }, 125 { 126 URL: "three/", 127 Status: http.StatusOK, 128 Golden: "testdata/golden/three.html", 129 }, 130 { 131 URL: "three/a.txt", 132 Status: http.StatusOK, 133 Golden: "testdata/golden/a.txt", 134 }, 135 { 136 URL: "", 137 Method: "HEAD", 138 Status: http.StatusOK, 139 Golden: "testdata/golden/indexhead.txt", 140 }, 141 { 142 URL: "one%25.txt", 143 Method: "HEAD", 144 Status: http.StatusOK, 145 Golden: "testdata/golden/onehead.txt", 146 }, 147 { 148 URL: "", 149 Method: "POST", 150 Status: http.StatusMethodNotAllowed, 151 Golden: "testdata/golden/indexpost.txt", 152 }, 153 { 154 URL: "one%25.txt", 155 Method: "POST", 156 Status: http.StatusMethodNotAllowed, 157 Golden: "testdata/golden/onepost.txt", 158 }, 159 { 160 URL: "two.txt", 161 Status: http.StatusOK, 162 Golden: "testdata/golden/two.txt", 163 }, 164 { 165 URL: "two.txt", 166 Status: http.StatusPartialContent, 167 Range: "bytes=2-5", 168 Golden: "testdata/golden/two2-5.txt", 169 }, 170 { 171 URL: "two.txt", 172 Status: http.StatusPartialContent, 173 Range: "bytes=0-6", 174 Golden: "testdata/golden/two-6.txt", 175 }, 176 { 177 URL: "two.txt", 178 Status: http.StatusPartialContent, 179 Range: "bytes=3-", 180 Golden: "testdata/golden/two3-.txt", 181 }, 182 } { 183 method := test.Method 184 if method == "" { 185 method = "GET" 186 } 187 req, err := http.NewRequest(method, testURL+test.URL, nil) 188 require.NoError(t, err) 189 if test.Range != "" { 190 req.Header.Add("Range", test.Range) 191 } 192 resp, err := http.DefaultClient.Do(req) 193 require.NoError(t, err) 194 assert.Equal(t, test.Status, resp.StatusCode, test.Golden) 195 body, err := ioutil.ReadAll(resp.Body) 196 require.NoError(t, err) 197 198 checkGolden(t, test.Golden, body) 199 } 200 } 201 202 func TestFinalise(t *testing.T) { 203 httpServer.Close() 204 httpServer.Wait() 205 }