Tests & CI, io.Reader > Multipart file.

Making some improvements to the future maintainability of the project,
namely in the form of tests. Also implemented a new "dist" command to
the Makefile that packs up the binaries, and will eventually be expanded
to do more legwork when prepping for a release.

Updated file providers to use io.Reader over an explicit multipart file,
and removed the handler in favour of a plain filename, since that was
it's primary purpose.
This commit is contained in:
Gabriel Simmer 2020-04-03 13:26:06 +01:00
parent c183003953
commit c28851fcc3
No known key found for this signature in database
GPG key ID: 33BA4D83B160A0A9
8 changed files with 179 additions and 16 deletions

54
.circleci/config.yml Normal file
View file

@ -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

1
.gitignore vendored
View file

@ -19,6 +19,7 @@ providers.yml
# Binary
nas
build/
*.db
.lock

View file

@ -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
test:
go test ./... -cover
dist: small small_pi
mkdir build
mv nas* build

View file

@ -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)

View file

@ -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

View file

@ -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
}

104
files/files_test.go Normal file
View file

@ -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)
}
}

View file

@ -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"]),