135 lines
3.6 KiB
Go
135 lines
3.6 KiB
Go
package main
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"io"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
"sync"
|
|
"testing"
|
|
)
|
|
|
|
// memObjects is the bucket in memory, for the tests of what the device process keeps.
|
|
type memObjects struct {
|
|
mu sync.Mutex
|
|
kept map[string][]byte
|
|
puts int
|
|
}
|
|
|
|
func newMemObjects() *memObjects { return &memObjects{kept: map[string][]byte{}} }
|
|
|
|
func (m *memObjects) Bucket() string { return "brother-test" }
|
|
|
|
func (m *memObjects) Has(_ context.Context, key string) (bool, error) {
|
|
m.mu.Lock()
|
|
defer m.mu.Unlock()
|
|
_, ok := m.kept[key]
|
|
return ok, nil
|
|
}
|
|
|
|
func (m *memObjects) Put(_ context.Context, key, _ string, data []byte) error {
|
|
m.mu.Lock()
|
|
defer m.mu.Unlock()
|
|
m.kept[key] = append([]byte(nil), data...)
|
|
m.puts++
|
|
return nil
|
|
}
|
|
|
|
func (m *memObjects) Get(_ context.Context, key string) ([]byte, error) {
|
|
m.mu.Lock()
|
|
defer m.mu.Unlock()
|
|
b, ok := m.kept[key]
|
|
if !ok {
|
|
return nil, fmt.Errorf("%s is not kept", key)
|
|
}
|
|
return b, nil
|
|
}
|
|
|
|
func (m *memObjects) keys() []string {
|
|
m.mu.Lock()
|
|
defer m.mu.Unlock()
|
|
var k []string
|
|
for key := range m.kept {
|
|
k = append(k, key)
|
|
}
|
|
return k
|
|
}
|
|
|
|
// 1453/AC8: the S3 client puts, heads and gets path-style under a Signature Version 4 header, and Store keeps
|
|
// a key once.
|
|
func TestTheBucketIsSpokenToPathStyleSignedAndKeptOnce(t *testing.T) {
|
|
var mu sync.Mutex
|
|
objects := map[string][]byte{}
|
|
var puts int
|
|
var auth string
|
|
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
mu.Lock()
|
|
defer mu.Unlock()
|
|
auth = r.Header.Get("Authorization")
|
|
if !strings.HasPrefix(r.URL.Path, "/scans/") {
|
|
http.Error(w, "path-style: /<bucket>/<key>", http.StatusBadRequest)
|
|
return
|
|
}
|
|
key := strings.TrimPrefix(r.URL.Path, "/scans/")
|
|
switch r.Method {
|
|
case http.MethodPut:
|
|
b, _ := io.ReadAll(r.Body)
|
|
objects[key] = b
|
|
puts++
|
|
case http.MethodHead, http.MethodGet:
|
|
b, ok := objects[key]
|
|
if !ok {
|
|
http.NotFound(w, r)
|
|
return
|
|
}
|
|
if r.Method == http.MethodGet {
|
|
w.Write(b)
|
|
}
|
|
}
|
|
}))
|
|
defer srv.Close()
|
|
host := strings.TrimPrefix(srv.URL, "http://")
|
|
at, port, _ := strings.Cut(host, ":")
|
|
s3 := NewS3(StoreFacts{Scheme: "http", At: at, Port: port, Bucket: "scans", Region: "us-east-1", Key: "AKID", Secret: "sek"})
|
|
ctx := context.Background()
|
|
for i := 0; i < 2; i++ {
|
|
if err := Store(ctx, s3, "abc.pdf", "application/pdf", []byte("%PDF-x")); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
}
|
|
if puts != 1 {
|
|
t.Errorf("%d puts, want the one: a key is kept once", puts)
|
|
}
|
|
got, err := s3.Get(ctx, "abc.pdf")
|
|
if err != nil || string(got) != "%PDF-x" {
|
|
t.Errorf("Get = %q, %v", got, err)
|
|
}
|
|
if !strings.HasPrefix(auth, "AWS4-HMAC-SHA256 Credential=AKID/") || !strings.Contains(auth, "SignedHeaders=") || strings.Contains(auth, "sek") {
|
|
t.Errorf("Authorization = %q", auth)
|
|
}
|
|
if _, err := s3.Get(ctx, "none.pdf"); err == nil {
|
|
t.Errorf("a key not kept was got")
|
|
}
|
|
}
|
|
|
|
// 1453: the store's facts are read from store.json, and one that names no bucket or key is refused by name.
|
|
func TestTheStoresFactsAreRead(t *testing.T) {
|
|
p := filepath.Join(t.TempDir(), "store.json")
|
|
os.WriteFile(p, []byte(`{"at":"minio.example","port":"9000","bucket":"brother","key":"k","secret":"s"}`), 0o600)
|
|
f, err := ReadStoreFacts(p)
|
|
if err != nil || f.Scheme != "http" || f.Region != "us-east-1" || f.Bucket != "brother" {
|
|
t.Errorf("facts = %+v, %v", f, err)
|
|
}
|
|
os.WriteFile(p, []byte(`{"at":"x"}`), 0o600)
|
|
if _, err := ReadStoreFacts(p); err == nil || !strings.Contains(err.Error(), "bucket") {
|
|
t.Errorf("error = %v", err)
|
|
}
|
|
if _, err := ReadStoreFacts(""); err == nil || !strings.Contains(err.Error(), "BROTHER_STORE") {
|
|
t.Errorf("error = %v", err)
|
|
}
|
|
}
|