github.com/ncw/rclone@v1.48.1-0.20190724201158-a35aa1360e3e/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/ncw/rclone/backend/local"
    12  	"github.com/ncw/rclone/cmd/serve/httplib"
    13  	"github.com/ncw/rclone/fs"
    14  	"github.com/ncw/rclone/fs/config"
    15  	"github.com/ncw/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  }