package frostfs // Tests for our FrostFS client code import ( "context" "crypto/ecdsa" "crypto/elliptic" "crypto/rand" "fmt" "os" "sync" "testing" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user" ) // Initialize storage backend for tests. func openStorage(t *testing.T) *Storage { t.Helper() cid := os.Getenv("FROSTFS_CID") // sample: "348WWfBKbS79Wbmm38MRE3oBoEDM5Ga1XXbGKGNyisDM" endpoint := os.Getenv("FROSTFS_ENDPOINT") // sample: "grpc://localhost:8802" if cid == "" || endpoint == "" { t.Skipf("one or more environment variables not set: FROSTFS_ENDPOINT, FROSTFS_CID") } key, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) // TODO: using ephemeral keys for now, later read from env vars if err != nil { t.Fatal(err) } storage, err := Open(endpoint, cid, key) if err != nil { t.Fatal(err) } return storage } // Save some bytes to FrostFS and clean up after. func TestObjectPutDelete(t *testing.T) { payload := []byte("Hello FrostFS!\n") storage := openStorage(t) ctx, cancel := context.WithCancel(context.Background()) t.Cleanup(cancel) oid, err := storage.Save(ctx, payload, "FileName", "hello_from_sdk.txt", "Tag", "foobar") if err != nil { t.Fatal(err) } t.Logf("saved object: %s", oid) err = storage.Delete(ctx, oid) if err != nil { t.Fatal(err) } t.Logf("deleted object: %s", oid) } // Check that FrostFS is in fact a content addressable storage. func TestMulipleObjects(t *testing.T) { payload := []byte("Multiple objects with same content should get the same object ID") ctx, cancel := context.WithCancel(context.Background()) t.Cleanup(cancel) var wg sync.WaitGroup objects := make(chan string) go func() { baseline := "" for { select { case <-ctx.Done(): return case obj, ok := <-objects: if !ok { return } if baseline == "" { baseline = obj continue } if obj != baseline { panic(fmt.Errorf("non-identical object id: %s != %s", baseline, obj)) } } } }() const testCount = 5 storage := openStorage(t) for i := 0; i < testCount; i++ { //nolint:intrange wg.Add(1) go func() { defer wg.Done() oid, err := storage.Save(ctx, payload, "FileName", "CAS.txt", "Tag", "test") if err != nil { panic(err) } err = storage.Delete(ctx, oid) if err != nil { panic(err) } t.Log(oid) }() } wg.Wait() } // Check opening wallet from file system. func TestLoadWallet(t *testing.T) { const ( walletPath = "client_test_wallet.json" walletAccount = "NWZnjbTKbzwtX6w1q5R3kbEKrnJ5bp1kn7" ) key, err := getKey(walletPath, "", "") if err != nil { t.Fatal(err) } if key2addr(key) != walletAccount { t.Fatalf("incorrect address for default account: want %s, got %s", walletAccount, key2addr(key)) } key, err = getKey(walletPath, walletAccount, "") if err != nil { t.Fatal(err) } if key2addr(key) != walletAccount { t.Fatalf("incorrect address for specific account: want %s, got %s", walletAccount, key2addr(key)) } } func key2addr(k *ecdsa.PrivateKey) string { var owner user.ID user.IDFromKey(&owner, k.PublicKey) return owner.String() }