296 lines
6.5 KiB
Go
296 lines
6.5 KiB
Go
// Copyright (c) HashiCorp, Inc.
|
|
// SPDX-License-Identifier: MPL-2.0
|
|
|
|
package storagepacker
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"testing"
|
|
|
|
"github.com/golang/protobuf/proto"
|
|
"github.com/golang/protobuf/ptypes"
|
|
log "github.com/hashicorp/go-hclog"
|
|
uuid "github.com/hashicorp/go-uuid"
|
|
"github.com/hashicorp/vault/helper/identity"
|
|
"github.com/hashicorp/vault/sdk/logical"
|
|
)
|
|
|
|
func BenchmarkStoragePacker(b *testing.B) {
|
|
storagePacker, err := NewStoragePacker(&logical.InmemStorage{}, log.New(&log.LoggerOptions{Name: "storagepackertest"}), "")
|
|
if err != nil {
|
|
b.Fatal(err)
|
|
}
|
|
|
|
ctx := context.Background()
|
|
|
|
for i := 0; i < b.N; i++ {
|
|
itemID, err := uuid.GenerateUUID()
|
|
if err != nil {
|
|
b.Fatal(err)
|
|
}
|
|
|
|
item := &Item{
|
|
ID: itemID,
|
|
}
|
|
|
|
err = storagePacker.PutItem(ctx, item)
|
|
if err != nil {
|
|
b.Fatal(err)
|
|
}
|
|
|
|
fetchedItem, err := storagePacker.GetItem(itemID)
|
|
if err != nil {
|
|
b.Fatal(err)
|
|
}
|
|
|
|
if fetchedItem == nil {
|
|
b.Fatalf("failed to read stored item with ID: %q, iteration: %d", item.ID, i)
|
|
}
|
|
|
|
if fetchedItem.ID != item.ID {
|
|
b.Fatalf("bad: item ID; expected: %q\n actual: %q", item.ID, fetchedItem.ID)
|
|
}
|
|
|
|
err = storagePacker.DeleteItem(ctx, item.ID)
|
|
if err != nil {
|
|
b.Fatal(err)
|
|
}
|
|
|
|
fetchedItem, err = storagePacker.GetItem(item.ID)
|
|
if err != nil {
|
|
b.Fatal(err)
|
|
}
|
|
if fetchedItem != nil {
|
|
b.Fatalf("failed to delete item")
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestStoragePacker(t *testing.T) {
|
|
storagePacker, err := NewStoragePacker(&logical.InmemStorage{}, log.New(&log.LoggerOptions{Name: "storagepackertest"}), "")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
ctx := context.Background()
|
|
|
|
// Persist a storage entry
|
|
item1 := &Item{
|
|
ID: "item1",
|
|
}
|
|
|
|
err = storagePacker.PutItem(ctx, item1)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
// Verify that it can be read
|
|
fetchedItem, err := storagePacker.GetItem(item1.ID)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if fetchedItem == nil {
|
|
t.Fatalf("failed to read the stored item")
|
|
}
|
|
|
|
if item1.ID != fetchedItem.ID {
|
|
t.Fatalf("bad: item ID; expected: %q\n actual: %q\n", item1.ID, fetchedItem.ID)
|
|
}
|
|
|
|
// Delete item1
|
|
err = storagePacker.DeleteItem(ctx, item1.ID)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
// Check that the deletion was successful
|
|
fetchedItem, err = storagePacker.GetItem(item1.ID)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
if fetchedItem != nil {
|
|
t.Fatalf("failed to delete item")
|
|
}
|
|
}
|
|
|
|
func TestStoragePacker_SerializeDeserializeComplexItem(t *testing.T) {
|
|
storagePacker, err := NewStoragePacker(&logical.InmemStorage{}, log.New(&log.LoggerOptions{Name: "storagepackertest"}), "")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
ctx := context.Background()
|
|
|
|
timeNow := ptypes.TimestampNow()
|
|
|
|
alias1 := &identity.Alias{
|
|
ID: "alias_id",
|
|
CanonicalID: "canonical_id",
|
|
MountType: "mount_type",
|
|
MountAccessor: "mount_accessor",
|
|
Metadata: map[string]string{
|
|
"aliasmkey": "aliasmvalue",
|
|
},
|
|
Name: "alias_name",
|
|
CreationTime: timeNow,
|
|
LastUpdateTime: timeNow,
|
|
MergedFromCanonicalIDs: []string{"merged_from_canonical_id"},
|
|
}
|
|
|
|
entity := &identity.Entity{
|
|
Aliases: []*identity.Alias{alias1},
|
|
ID: "entity_id",
|
|
Name: "entity_name",
|
|
Metadata: map[string]string{
|
|
"testkey1": "testvalue1",
|
|
"testkey2": "testvalue2",
|
|
},
|
|
CreationTime: timeNow,
|
|
LastUpdateTime: timeNow,
|
|
BucketKey: "entity_hash",
|
|
MergedEntityIDs: []string{"merged_entity_id1", "merged_entity_id2"},
|
|
Policies: []string{"policy1", "policy2"},
|
|
}
|
|
|
|
marshaledEntity, err := ptypes.MarshalAny(entity)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
err = storagePacker.PutItem(ctx, &Item{
|
|
ID: entity.ID,
|
|
Message: marshaledEntity,
|
|
})
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
itemFetched, err := storagePacker.GetItem(entity.ID)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
var itemDecoded identity.Entity
|
|
err = ptypes.UnmarshalAny(itemFetched.Message, &itemDecoded)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
if !proto.Equal(&itemDecoded, entity) {
|
|
t.Fatalf("bad: expected: %#v\nactual: %#v\n", entity, itemDecoded)
|
|
}
|
|
}
|
|
|
|
func TestStoragePacker_DeleteMultiple(t *testing.T) {
|
|
storagePacker, err := NewStoragePacker(&logical.InmemStorage{}, log.New(&log.LoggerOptions{Name: "storagepackertest"}), "")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
ctx := context.Background()
|
|
|
|
// Persist a storage entry
|
|
for i := 0; i < 100; i++ {
|
|
item := &Item{
|
|
ID: fmt.Sprintf("item%d", i),
|
|
}
|
|
|
|
err = storagePacker.PutItem(ctx, item)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
// Verify that it can be read
|
|
fetchedItem, err := storagePacker.GetItem(item.ID)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if fetchedItem == nil {
|
|
t.Fatalf("failed to read the stored item")
|
|
}
|
|
|
|
if item.ID != fetchedItem.ID {
|
|
t.Fatalf("bad: item ID; expected: %q\n actual: %q\n", item.ID, fetchedItem.ID)
|
|
}
|
|
}
|
|
|
|
itemsToDelete := make([]string, 0, 50)
|
|
for i := 1; i < 100; i += 2 {
|
|
itemsToDelete = append(itemsToDelete, fmt.Sprintf("item%d", i))
|
|
}
|
|
|
|
err = storagePacker.DeleteMultipleItems(ctx, nil, itemsToDelete)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
// Check that the deletion was successful
|
|
for i := 0; i < 100; i++ {
|
|
fetchedItem, err := storagePacker.GetItem(fmt.Sprintf("item%d", i))
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
if i%2 == 0 && fetchedItem == nil {
|
|
t.Fatal("expected item not found")
|
|
}
|
|
if i%2 == 1 && fetchedItem != nil {
|
|
t.Fatalf("failed to delete item")
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestStoragePacker_DeleteMultiple_ALL(t *testing.T) {
|
|
storagePacker, err := NewStoragePacker(&logical.InmemStorage{}, log.New(&log.LoggerOptions{Name: "storagepackertest"}), "")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
ctx := context.Background()
|
|
|
|
// Persist a storage entry
|
|
itemsToDelete := make([]string, 0, 10000)
|
|
for i := 0; i < 10000; i++ {
|
|
item := &Item{
|
|
ID: fmt.Sprintf("item%d", i),
|
|
}
|
|
|
|
err = storagePacker.PutItem(ctx, item)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
// Verify that it can be read
|
|
fetchedItem, err := storagePacker.GetItem(item.ID)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if fetchedItem == nil {
|
|
t.Fatalf("failed to read the stored item")
|
|
}
|
|
|
|
if item.ID != fetchedItem.ID {
|
|
t.Fatalf("bad: item ID; expected: %q\n actual: %q\n", item.ID, fetchedItem.ID)
|
|
}
|
|
|
|
itemsToDelete = append(itemsToDelete, fmt.Sprintf("item%d", i))
|
|
}
|
|
|
|
err = storagePacker.DeleteMultipleItems(ctx, nil, itemsToDelete)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
// Check that the deletion was successful
|
|
for _, item := range itemsToDelete {
|
|
fetchedItem, err := storagePacker.GetItem(item)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if fetchedItem != nil {
|
|
t.Fatal("item not deleted")
|
|
}
|
|
}
|
|
}
|