package container_test import ( "crypto/sha256" "strconv" "testing" "time" containergrpc "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/container/grpc" netmapgrpc "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/netmap/grpc" refs "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs/grpc" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" cidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id/test" containertest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/test" frostfscrypto "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/crypto" netmaptest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap/test" usertest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user/test" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/version" "github.com/google/uuid" "github.com/nspcc-dev/neo-go/pkg/crypto/keys" "github.com/stretchr/testify/require" "google.golang.org/protobuf/proto" ) func TestPlacementPolicyEncoding(t *testing.T) { v := containertest.Container() t.Run("binary", func(t *testing.T) { v2 := container.NewContainer() require.NoError(t, v2.Unmarshal(v.Marshal())) var c1, c2 containergrpc.Container v.WriteToV2(&c1) v2.WriteToV2(&c2) require.True(t, proto.Equal(&c1, &c2)) }) t.Run("json", func(t *testing.T) { data, err := v.MarshalJSON() require.NoError(t, err) v2 := container.NewContainer() require.NoError(t, v2.UnmarshalJSON(data)) var c1, c2 containergrpc.Container v.WriteToV2(&c1) v2.WriteToV2(&c2) require.True(t, proto.Equal(&c1, &c2)) }) } func TestContainer_Init(t *testing.T) { val := containertest.Container() val.Init() var msg containergrpc.Container val.WriteToV2(&msg) binNonce := msg.GetNonce() var nonce uuid.UUID require.NoError(t, nonce.UnmarshalBinary(binNonce)) require.EqualValues(t, 4, nonce.Version()) verV2 := msg.GetVersion() require.NotNil(t, verV2) ver := version.NewVersion() ver.ReadFromV2(verV2) var v1, v2 refs.Version version.Current().WriteToV2(&v1) ver.WriteToV2(&v2) require.True(t, proto.Equal(&v1, &v2)) val2 := container.NewContainer() require.NoError(t, val2.ReadFromV2(&msg)) var c1, c2 containergrpc.Container val.WriteToV2(&c1) val2.WriteToV2(&c2) require.True(t, proto.Equal(&c1, &c2)) } func TestContainer_Owner(t *testing.T) { val := container.NewContainer() require.Zero(t, val.Owner()) val = containertest.Container() owner := *usertest.ID() val.SetOwner(owner) var msg containergrpc.Container val.WriteToV2(&msg) var msgOwner refs.OwnerID owner.WriteToV2(&msgOwner) require.True(t, proto.Equal(&msgOwner, msg.GetOwnerId())) val2 := container.NewContainer() require.NoError(t, val2.ReadFromV2(&msg)) require.True(t, val2.Owner().Equals(owner)) } func TestContainer_BasicACL(t *testing.T) { val := container.NewContainer() require.Zero(t, val.BasicACL()) val = containertest.Container() basicACL := containertest.BasicACL() val.SetBasicACL(basicACL) var msg containergrpc.Container val.WriteToV2(&msg) require.EqualValues(t, basicACL.Bits(), msg.GetBasicAcl()) val2 := container.NewContainer() require.NoError(t, val2.ReadFromV2(&msg)) require.Equal(t, basicACL, val2.BasicACL()) } func TestContainer_PlacementPolicy(t *testing.T) { val := container.NewContainer() require.Zero(t, val.PlacementPolicy()) val = containertest.Container() pp := netmaptest.PlacementPolicy() val.SetPlacementPolicy(pp) var msgPolicy netmapgrpc.PlacementPolicy pp.WriteToV2(&msgPolicy) var msg containergrpc.Container val.WriteToV2(&msg) require.True(t, proto.Equal(&msgPolicy, msg.GetPlacementPolicy())) val2 := container.NewContainer() require.NoError(t, val2.ReadFromV2(&msg)) var p1, p2 netmapgrpc.PlacementPolicy pp.WriteToV2(&p1) val2.PlacementPolicy().WriteToV2(&p2) require.True(t, proto.Equal(&p1, &p2)) } func assertContainsAttribute(t *testing.T, m *containergrpc.Container, key, val string) { var msgAttr containergrpc.Container_Attribute msgAttr.SetKey(key) msgAttr.SetValue(val) var found bool for _, attr := range m.GetAttributes() { if found = proto.Equal(attr, &msgAttr); found { break } } require.True(t, found, "Attribute has not been found") } func TestContainer_Attribute(t *testing.T) { const attrKey1, attrKey2 = containergrpc.SysAttributePrefix + "key1", containergrpc.SysAttributePrefixNeoFS + "key2" const attrVal1, attrVal2 = "val1", "val2" val := containertest.Container() val.SetAttribute(attrKey1, attrVal1) val.SetAttribute(attrKey2, attrVal2) var i int val.IterateUserAttributes(func(key, val string) { i++ }) require.Equal(t, 1, i) var msg containergrpc.Container val.WriteToV2(&msg) require.GreaterOrEqual(t, len(msg.GetAttributes()), 2) assertContainsAttribute(t, &msg, attrKey1, attrVal1) assertContainsAttribute(t, &msg, attrKey2, attrVal2) val2 := container.NewContainer() require.NoError(t, val2.ReadFromV2(&msg)) require.Equal(t, attrVal1, val2.Attribute(attrKey1)) require.Equal(t, attrVal2, val2.Attribute(attrKey2)) m := map[string]string{} val2.IterateAttributes(func(key, val string) { m[key] = val }) require.GreaterOrEqual(t, len(m), 2) require.Equal(t, attrVal1, m[attrKey1]) require.Equal(t, attrVal2, m[attrKey2]) val2.SetAttribute(attrKey1, attrVal1+"_") require.Equal(t, attrVal1+"_", val2.Attribute(attrKey1)) } func TestSetName(t *testing.T) { val := container.NewContainer() require.Panics(t, func() { container.SetName(val, "") }) val = containertest.Container() const name = "some name" container.SetName(val, name) var msg containergrpc.Container val.WriteToV2(&msg) assertContainsAttribute(t, &msg, "Name", name) val2 := container.NewContainer() require.NoError(t, val2.ReadFromV2(&msg)) require.Equal(t, name, container.Name(val2)) } func TestSetCreationTime(t *testing.T) { val := container.NewContainer() require.Zero(t, container.CreatedAt(val).Unix()) val = containertest.Container() creat := time.Now() container.SetCreationTime(val, creat) var msg containergrpc.Container val.WriteToV2(&msg) assertContainsAttribute(t, &msg, "Timestamp", strconv.FormatInt(creat.Unix(), 10)) val2 := container.NewContainer() require.NoError(t, val2.ReadFromV2(&msg)) require.Equal(t, creat.Unix(), container.CreatedAt(val2).Unix()) } func TestDisableHomomorphicHashing(t *testing.T) { var val container.Container require.False(t, container.IsHomomorphicHashingDisabled(val)) val = containertest.Container() container.DisableHomomorphicHashing(val) var msg containergrpc.Container val.WriteToV2(&msg) assertContainsAttribute(t, &msg, containergrpc.SysAttributePrefix+"DISABLE_HOMOMORPHIC_HASHING", "true") val2 := container.NewContainer() require.NoError(t, val2.ReadFromV2(&msg)) require.True(t, container.IsHomomorphicHashingDisabled(val2)) } func TestWriteDomain(t *testing.T) { val := container.NewContainer() require.Zero(t, container.ReadDomain(val).Name()) val = containertest.Container() const name = "domain name" var d container.Domain d.SetName(name) container.WriteDomain(val, d) var msg containergrpc.Container val.WriteToV2(&msg) assertContainsAttribute(t, &msg, containergrpc.SysAttributeName, name) assertContainsAttribute(t, &msg, containergrpc.SysAttributeZone, "container") const zone = "domain zone" d.SetZone(zone) container.WriteDomain(val, d) val.WriteToV2(&msg) assertContainsAttribute(t, &msg, containergrpc.SysAttributeZone, zone) val2 := container.NewContainer() require.NoError(t, val2.ReadFromV2(&msg)) require.Equal(t, d, container.ReadDomain(val2)) } func TestCalculateID(t *testing.T) { val := containertest.Container() require.False(t, container.AssertID(cidtest.ID(), val)) var id cid.ID container.CalculateID(&id, val) var msg refs.ContainerID id.WriteToV2(&msg) h := sha256.Sum256(val.Marshal()) require.Equal(t, h[:], msg.GetValue()) var id2 cid.ID require.NoError(t, id2.ReadFromV2(&msg)) require.True(t, container.AssertID(id2, val)) } func TestCalculateSignature(t *testing.T) { key, err := keys.NewPrivateKey() require.NoError(t, err) val := containertest.Container() sig := frostfscrypto.NewSignature() require.NoError(t, container.CalculateSignature(&sig, val, key.PrivateKey)) var msg refs.Signature sig.WriteToV2(&msg) var sig2 frostfscrypto.Signature require.NoError(t, sig2.ReadFromV2(&msg)) require.True(t, container.VerifySignature(&sig2, &val)) }