Initial go port of epics
This commit is contained in:
@@ -0,0 +1,232 @@
|
||||
package storage_test
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"testing"
|
||||
|
||||
"github.com/uopi/uopi/internal/storage"
|
||||
)
|
||||
|
||||
const sampleXML = `<interface id="test-if" name="Test Interface" version="1"><widget/></interface>`
|
||||
|
||||
func newStore(t *testing.T) *storage.Store {
|
||||
t.Helper()
|
||||
s, err := storage.New(t.TempDir())
|
||||
if err != nil {
|
||||
t.Fatalf("New: %v", err)
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------- //
|
||||
// List //
|
||||
// -------------------------------------------------------------------------- //
|
||||
|
||||
func TestListEmpty(t *testing.T) {
|
||||
s := newStore(t)
|
||||
list, err := s.List()
|
||||
if err != nil {
|
||||
t.Fatalf("List: %v", err)
|
||||
}
|
||||
if len(list) != 0 {
|
||||
t.Errorf("expected empty list, got %d items", len(list))
|
||||
}
|
||||
}
|
||||
|
||||
func TestListAfterCreate(t *testing.T) {
|
||||
s := newStore(t)
|
||||
if _, err := s.Create([]byte(sampleXML)); err != nil {
|
||||
t.Fatalf("Create: %v", err)
|
||||
}
|
||||
list, err := s.List()
|
||||
if err != nil {
|
||||
t.Fatalf("List: %v", err)
|
||||
}
|
||||
if len(list) != 1 {
|
||||
t.Fatalf("expected 1 item, got %d", len(list))
|
||||
}
|
||||
if list[0].Name != "Test Interface" {
|
||||
t.Errorf("Name = %q, want %q", list[0].Name, "Test Interface")
|
||||
}
|
||||
if list[0].Version != 1 {
|
||||
t.Errorf("Version = %d, want 1", list[0].Version)
|
||||
}
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------- //
|
||||
// Create + Get //
|
||||
// -------------------------------------------------------------------------- //
|
||||
|
||||
func TestCreateAndGet(t *testing.T) {
|
||||
s := newStore(t)
|
||||
id, err := s.Create([]byte(sampleXML))
|
||||
if err != nil {
|
||||
t.Fatalf("Create: %v", err)
|
||||
}
|
||||
if id == "" {
|
||||
t.Fatal("Create returned empty ID")
|
||||
}
|
||||
|
||||
data, err := s.Get(id)
|
||||
if err != nil {
|
||||
t.Fatalf("Get(%q): %v", id, err)
|
||||
}
|
||||
if string(data) != sampleXML {
|
||||
t.Errorf("Get returned %q, want %q", data, sampleXML)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCreateUsesEmbeddedID(t *testing.T) {
|
||||
s := newStore(t)
|
||||
id, err := s.Create([]byte(sampleXML))
|
||||
if err != nil {
|
||||
t.Fatalf("Create: %v", err)
|
||||
}
|
||||
// ID derived from xml id attr or name slug.
|
||||
if id == "" {
|
||||
t.Error("ID should not be empty")
|
||||
}
|
||||
}
|
||||
|
||||
func TestCreateDuplicateGetsUniqueID(t *testing.T) {
|
||||
s := newStore(t)
|
||||
id1, err := s.Create([]byte(sampleXML))
|
||||
if err != nil {
|
||||
t.Fatalf("first Create: %v", err)
|
||||
}
|
||||
id2, err := s.Create([]byte(sampleXML))
|
||||
if err != nil {
|
||||
t.Fatalf("second Create: %v", err)
|
||||
}
|
||||
if id1 == id2 {
|
||||
t.Errorf("duplicate Create returned same ID %q", id1)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCreateInvalidXML(t *testing.T) {
|
||||
s := newStore(t)
|
||||
_, err := s.Create([]byte("not xml"))
|
||||
if err == nil {
|
||||
t.Error("expected error for invalid XML")
|
||||
}
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------- //
|
||||
// Get errors //
|
||||
// -------------------------------------------------------------------------- //
|
||||
|
||||
func TestGetNotFound(t *testing.T) {
|
||||
s := newStore(t)
|
||||
_, err := s.Get("does-not-exist")
|
||||
if !errors.Is(err, storage.ErrNotFound) {
|
||||
t.Errorf("Get missing: want ErrNotFound, got %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetInvalidID(t *testing.T) {
|
||||
s := newStore(t)
|
||||
_, err := s.Get("../traversal")
|
||||
if !errors.Is(err, storage.ErrNotFound) {
|
||||
t.Errorf("Get path-traversal ID: want ErrNotFound, got %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetEmptyID(t *testing.T) {
|
||||
s := newStore(t)
|
||||
_, err := s.Get("")
|
||||
if !errors.Is(err, storage.ErrNotFound) {
|
||||
t.Errorf("Get empty ID: want ErrNotFound, got %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------- //
|
||||
// Update //
|
||||
// -------------------------------------------------------------------------- //
|
||||
|
||||
func TestUpdate(t *testing.T) {
|
||||
s := newStore(t)
|
||||
id, err := s.Create([]byte(sampleXML))
|
||||
if err != nil {
|
||||
t.Fatalf("Create: %v", err)
|
||||
}
|
||||
|
||||
updated := `<interface id="test-if" name="Updated" version="2"><widget/></interface>`
|
||||
if err := s.Update(id, []byte(updated)); err != nil {
|
||||
t.Fatalf("Update: %v", err)
|
||||
}
|
||||
|
||||
data, err := s.Get(id)
|
||||
if err != nil {
|
||||
t.Fatalf("Get after update: %v", err)
|
||||
}
|
||||
if string(data) != updated {
|
||||
t.Errorf("post-update content mismatch")
|
||||
}
|
||||
}
|
||||
|
||||
func TestUpdateNotFound(t *testing.T) {
|
||||
s := newStore(t)
|
||||
err := s.Update("no-such-id", []byte(sampleXML))
|
||||
if !errors.Is(err, storage.ErrNotFound) {
|
||||
t.Errorf("Update missing: want ErrNotFound, got %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------- //
|
||||
// Delete //
|
||||
// -------------------------------------------------------------------------- //
|
||||
|
||||
func TestDelete(t *testing.T) {
|
||||
s := newStore(t)
|
||||
id, err := s.Create([]byte(sampleXML))
|
||||
if err != nil {
|
||||
t.Fatalf("Create: %v", err)
|
||||
}
|
||||
if err := s.Delete(id); err != nil {
|
||||
t.Fatalf("Delete: %v", err)
|
||||
}
|
||||
_, err = s.Get(id)
|
||||
if !errors.Is(err, storage.ErrNotFound) {
|
||||
t.Errorf("Get after delete: want ErrNotFound, got %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestDeleteNotFound(t *testing.T) {
|
||||
s := newStore(t)
|
||||
err := s.Delete("ghost")
|
||||
if !errors.Is(err, storage.ErrNotFound) {
|
||||
t.Errorf("Delete missing: want ErrNotFound, got %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------- //
|
||||
// Clone //
|
||||
// -------------------------------------------------------------------------- //
|
||||
|
||||
func TestClone(t *testing.T) {
|
||||
s := newStore(t)
|
||||
id, err := s.Create([]byte(sampleXML))
|
||||
if err != nil {
|
||||
t.Fatalf("Create: %v", err)
|
||||
}
|
||||
newID, err := s.Clone(id)
|
||||
if err != nil {
|
||||
t.Fatalf("Clone: %v", err)
|
||||
}
|
||||
if newID == id {
|
||||
t.Error("Clone should produce a different ID")
|
||||
}
|
||||
orig, _ := s.Get(id)
|
||||
copy, _ := s.Get(newID)
|
||||
if string(orig) != string(copy) {
|
||||
t.Error("Clone content should match original")
|
||||
}
|
||||
}
|
||||
|
||||
func TestCloneNotFound(t *testing.T) {
|
||||
s := newStore(t)
|
||||
_, err := s.Clone("ghost")
|
||||
if !errors.Is(err, storage.ErrNotFound) {
|
||||
t.Errorf("Clone missing: want ErrNotFound, got %v", err)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user