diff --git a/.circleci/config.yml b/.circleci/config.yml new file mode 100644 index 0000000..a42d231 --- /dev/null +++ b/.circleci/config.yml @@ -0,0 +1,54 @@ +version: 2.1 +jobs: + build: + docker: + - image: cimg/go:1.14 + steps: + - checkout + - restore_cache: + keys: + - go-mod-{{ checksum "go.sum" }}-v1 + - go-mod-{{ checksum "go.sum" }} + - go-mod + - restore_cache: + keys: + - upx-3.96 + - run: + name: Install UPX + command: | + if ! type "upx" > /dev/null; then + wget https://github.com/upx/upx/releases/download/v3.96/upx-3.96-amd64_linux.tar.xz + tar xf upx-3.96-amd64_linux.tar.xz + sudo mv upx-3.96-amd64_linux/upx /usr/local/bin + chmod +x /usr/local/bin/upx + fi + - run: + command: make dist + - store_artifacts: + path: /go/src/github.com/gmemstr/build + - save_cache: + key: go-mod-{{ checksum "go.sum" }}-v1 + paths: + - /go/pkg/mod + - save_cache: + key: upx-3.96 + paths: + - /usr/local/bin/upx + test: + docker: + - image: cimg/go:1.14 + steps: + - checkout + - restore_cache: + keys: + - go-mod-{{ checksum "go.sum" }}-v1 + - go-mod-{{ checksum "go.sum" }} + - go-mod + - run: + command: make test +workflows: + version: 2 + build-and-test: + jobs: + - build + - test diff --git a/.gitignore b/.gitignore index 7be6860..5ae4bb7 100644 --- a/.gitignore +++ b/.gitignore @@ -19,6 +19,7 @@ providers.yml # Binary nas +build/ *.db .lock diff --git a/Makefile b/Makefile index 34befea..e59f525 100644 --- a/Makefile +++ b/Makefile @@ -4,15 +4,22 @@ build: go build pi: - env GOOS=linux GOARCH=arm GOARM=5 go build + env GOOS=linux GOARCH=arm GOARM=5 go build -o nas-pi small: go build -ldflags="-s -w" upx --brute nas small_pi: - env GOOS=linux GOARCH=arm GOARM=5 go build -ldflags="-s -w" - upx --brute nas + env GOOS=linux GOARCH=arm GOARM=5 go build -o nas-arm -ldflags="-s -w" + upx --brute nas-arm run: - go run webserver.go \ No newline at end of file + go run webserver.go + +test: + go test ./... -cover + +dist: small small_pi + mkdir build + mv nas* build diff --git a/files/backblaze.go b/files/backblaze.go index 2a3e544..9928dd6 100644 --- a/files/backblaze.go +++ b/files/backblaze.go @@ -7,7 +7,6 @@ import ( "fmt" "io" "io/ioutil" - "mime/multipart" "net/http" "strings" ) @@ -190,7 +189,7 @@ func (bp *BackblazeProvider) ViewFile(path string, w io.Writer) { } } -func (bp *BackblazeProvider) SaveFile(file multipart.File, handler *multipart.FileHeader, path string) bool { +func (bp *BackblazeProvider) SaveFile(file io.Reader, filename string, path string) bool { client := &http.Client{} bucketIdPayload := fmt.Sprintf(`{"bucketId": "%s"}`, bp.Bucket) @@ -240,10 +239,10 @@ func (bp *BackblazeProvider) SaveFile(file multipart.File, handler *multipart.Fi fileSha.Write(bodyBytes) req.Header.Add("Authorization", data.AuthToken) - req.Header.Add("X-Bz-File-Name", handler.Filename) + req.Header.Add("X-Bz-File-Name", filename) req.Header.Add("Content-Type", "b2/x-auto") req.Header.Add("X-Bz-Content-Sha1", fmt.Sprintf("%x", fileSha.Sum(nil))) - req.ContentLength = handler.Size + req.ContentLength = int64(len(bodyBytes)) // Upload in background. res, err = client.Do(req) diff --git a/files/disk.go b/files/disk.go index 7d6882c..3aa67bd 100644 --- a/files/disk.go +++ b/files/disk.go @@ -4,7 +4,6 @@ import ( "fmt" "io" "io/ioutil" - "mime/multipart" "os" "strings" ) @@ -55,9 +54,9 @@ func (dp *DiskProvider) ViewFile(path string, w io.Writer) { } } -func (dp *DiskProvider) SaveFile(file multipart.File, handler *multipart.FileHeader, path string) bool { - filename := strings.Join([]string{dp.Location,path,handler.Filename}, "/") - f, err := os.OpenFile(filename, os.O_WRONLY|os.O_CREATE, 0666) +func (dp *DiskProvider) SaveFile(file io.Reader, filename string, path string) bool { + fullPath := strings.Join([]string{dp.Location,path,filename}, "/") + f, err := os.OpenFile(fullPath, os.O_WRONLY|os.O_CREATE, 0666) if err != nil { fmt.Println(err.Error()) return false diff --git a/files/fileprovider.go b/files/fileprovider.go index 1fff12a..9dd8175 100644 --- a/files/fileprovider.go +++ b/files/fileprovider.go @@ -2,7 +2,6 @@ package files import ( "io" - "mime/multipart" ) type FileProvider struct { @@ -33,7 +32,7 @@ type FileProviderInterface interface { Setup(args map[string]string) bool GetDirectory(path string) Directory ViewFile(path string, w io.Writer) - SaveFile(file multipart.File, handler *multipart.FileHeader, path string) bool + SaveFile(file io.Reader, filename string, path string) bool DetermineType(path string) string } @@ -50,7 +49,7 @@ func (f FileProvider) ViewFile(path string, w io.Writer) { return } -func (f FileProvider) SaveFile(file multipart.File, handler *multipart.FileHeader, path string) bool { +func (f FileProvider) SaveFile(file io.Reader, filename string, path string) bool { return false } diff --git a/files/files_test.go b/files/files_test.go new file mode 100644 index 0000000..a588625 --- /dev/null +++ b/files/files_test.go @@ -0,0 +1,104 @@ +package files + +import ( + "bytes" + "fmt" + "io/ioutil" + "os" + "reflect" + "testing" +) + +const DISK_TESTING_GROUNDS = ".testing_data_directory/" + +// Test basic file provider. +// Should return, essentially, nothing. Can be used as a template for other providers. +func TestFileProvider(t *testing.T) { + fp := FileProvider{} + + setup := fp.Setup(map[string]string{}); if setup != false { + t.Errorf("Default FileProvider Setup() returned %v, expected false.", setup) + } + + getdirectory := fp.GetDirectory(""); if len(getdirectory.Files) != 0 { + t.Errorf("Default FileProvider GetDirectory() files returned %v, expected none.", getdirectory.Files) + } + + var w bytes.Buffer + fp.ViewFile("", &w); if len(w.Bytes()) > 0 { + t.Errorf("Default FileProvider ViewFile() %v, expected nothing.", w) + } + + savefile := fp.SaveFile(nil, "", ""); if savefile != false { + t.Errorf("Default FileProvider SaveFile() attempted to save a file.") + } + + determinetype := fp.DetermineType(""); if determinetype != "" { + t.Errorf("Default FileProvider DetermineType() did not return an empty string.") + } +} + +// Test functions provided by fileutils, which do not return anything. +func TestFileUtils(t *testing.T) { + ProviderConfig = map[string]FileProvider{ + "test": { + Name: "test_disk", + Provider: "disk", + Location: DISK_TESTING_GROUNDS, + }, + } + var i FileProviderInterface + TranslateProvider("test", &i) + typeof := reflect.TypeOf(i); if typeof != (reflect.TypeOf(&DiskProvider{})) { + t.Errorf("TranslateProvider() returned %v, expected DiskProvider{}", typeof) + } + + SetupProviders() + if Providers["test"] == nil { + t.Errorf("SetupProviders() did not setup test provider") + } +} + +func TestDiskProvider(t *testing.T) { + // Initialize testing data + t.Cleanup(DiskProviderTestCleanup) + err := os.Mkdir(DISK_TESTING_GROUNDS, 0755) + if err != nil { + t.Fatalf("Failed to create testing directory for DiskProvider: %v", err.Error()) + } + err = ioutil.WriteFile(DISK_TESTING_GROUNDS + "testing.txt", []byte("testing file!"), 0755) + if err != nil { + t.Fatalf("Failed to create testing file for DiskProvider: %v", err.Error()) + } + + dp := DiskProvider{FileProvider{Location: DISK_TESTING_GROUNDS}} + setup := dp.Setup(map[string]string{}); if setup != true { + t.Errorf("DiskProvider Setup() returned %v, expected true.", setup) + } + + getdirectory := dp.GetDirectory(""); if len(getdirectory.Files) != 1 { + t.Errorf("DiskProvider GetDirectory() files returned %v, expected 1.", getdirectory.Files) + } + + var w bytes.Buffer + dp.ViewFile("testing.txt", &w); if w.String() != "testing file!" { + fmt.Println(w) + t.Errorf("DiskProvider ViewFile() returned %v, expected \"testing file!\".", w.String()) + } + + testfile := bytes.NewReader([]byte("second test file!")) + savefile := dp.SaveFile(testfile, "second_test.txt", ""); if savefile != true { + t.Errorf("DiskProvider SaveFile() could not save a file.") + } + + determinetype := dp.DetermineType("second_test.txt"); if determinetype != "file" { + t.Errorf("DiskProvider DetermineType() returned %v, expected \"file\".", determinetype) + } +} + +func DiskProviderTestCleanup() { + err := os.RemoveAll(DISK_TESTING_GROUNDS) + if err != nil { + fmt.Printf("Unable to remove testing directory %v, please manully remove it", DISK_TESTING_GROUNDS) + } +} \ No newline at end of file diff --git a/router/filerouter.go b/router/filerouter.go index 55ff8b4..c3f5797 100644 --- a/router/filerouter.go +++ b/router/filerouter.go @@ -54,7 +54,7 @@ func HandleProvider() Handler { file, handler, err := r.FormFile("file") defer file.Close() - success := provider.SaveFile(file, handler, vars["file"]) + success := provider.SaveFile(file, handler.Filename, vars["file"]) if !success { return &HTTPError{ Message: fmt.Sprintf("error saving file %s\n", vars["file"]),