89 lines
2.8 KiB
Go
89 lines
2.8 KiB
Go
//go:build integration
|
|
|
|
package process
|
|
|
|
import (
|
|
"errors"
|
|
"strings"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/nats-io/nats.go/jetstream"
|
|
|
|
stdio "git.novox.be/novox/mesh-sdk/go"
|
|
)
|
|
|
|
// 1188/AC1: given a process connection to a test bus granted the bucket mesh-mail_sends, when it creates a
|
|
// key, reads it, and updates it with the revision it read, then each succeeds and returns the new
|
|
// revision; an update with a stale revision fails as stdio.ErrChanged; a create of an existing key fails
|
|
// as stdio.ErrChanged.
|
|
func TestStateCreateGetUpdateOnAGrantedBucket(t *testing.T) {
|
|
url, account := grantedSendProcess(t)
|
|
_, adminJetStream := adminJS(t, url)
|
|
if _, err := adminJetStream.CreateKeyValue(ctxFor(t), jetstream.KeyValueConfig{Bucket: "mesh-mail_sends"}); err != nil {
|
|
t.Fatalf("the admin could not make the bucket: %v", err)
|
|
}
|
|
|
|
conn, err := Connect(account)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
defer conn.Close()
|
|
s := conn.State("sends")
|
|
|
|
rev, err := s.Create("key", map[string]any{"v": 1})
|
|
if err != nil {
|
|
t.Fatalf("Create on a granted bucket: %v", err)
|
|
}
|
|
if rev == 0 {
|
|
t.Fatal("Create returned no revision")
|
|
}
|
|
|
|
e, err := s.Get("key")
|
|
if err != nil || e == nil {
|
|
t.Fatalf("Get after Create: %+v, %v", e, err)
|
|
}
|
|
if e.Revision != rev || string(e.Value) != `{"v":1}` {
|
|
t.Fatalf("Get read back %+v, want revision %d and {\"v\":1}", e, rev)
|
|
}
|
|
|
|
rev2, err := s.Update("key", map[string]any{"v": 2}, rev)
|
|
if err != nil {
|
|
t.Fatalf("Update at the revision read: %v", err)
|
|
}
|
|
if rev2 == rev {
|
|
t.Fatal("Update did not return a new revision")
|
|
}
|
|
|
|
if _, err := s.Update("key", map[string]any{"v": 3}, rev); !errors.Is(err, stdio.ErrChanged) {
|
|
t.Fatalf("Update at a stale revision: %v, want stdio.ErrChanged", err)
|
|
}
|
|
|
|
if _, err := s.Create("key", map[string]any{"v": 4}); !errors.Is(err, stdio.ErrChanged) {
|
|
t.Fatalf("Create of an existing key: %v, want stdio.ErrChanged", err)
|
|
}
|
|
}
|
|
|
|
// 1188/AC4: given an account not granted a bucket, when it writes there, then the bus's refusal comes back
|
|
// as an error naming the bucket. A denied publish is refused only as an async protocol error with no
|
|
// reply (never a reply naming the refusal), so StateTimeout is shortened for this test alone.
|
|
func TestStateRefusesAnUngrantedBucketNamingIt(t *testing.T) {
|
|
old := StateTimeout
|
|
StateTimeout = 2 * time.Second
|
|
t.Cleanup(func() { StateTimeout = old })
|
|
|
|
_, account := grantedSendProcess(t)
|
|
conn, err := Connect(account)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
defer conn.Close()
|
|
|
|
s := conn.State("unrelated")
|
|
if _, err := s.Create("key", map[string]any{"v": 1}); err == nil {
|
|
t.Fatal("writing to an ungranted bucket was not refused")
|
|
} else if !strings.Contains(err.Error(), "mesh-mail_unrelated") {
|
|
t.Errorf("the refusal %q does not name the bucket mesh-mail_unrelated", err.Error())
|
|
}
|
|
}
|