Files
mesh-catalog/modules/brother/cmd/brother/objects_test.go
T

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