diff --git a/netmap/node_info.go b/netmap/node_info.go index 98d6fe5b..5f2592ff 100644 --- a/netmap/node_info.go +++ b/netmap/node_info.go @@ -460,6 +460,40 @@ func (x NodeInfo) IterateAttributes(f func(key, value string)) { } } +// GetAttributes returns all the node attributes. +// Each attribute is a [2]string slice: {"key", "value"}. +// +// See also Attribute, IterateAttributes. +func (x NodeInfo) GetAttributes() [][2]string { + attrs := make([][2]string, len(x.m.GetAttributes())) + for i, attr := range x.m.GetAttributes() { + attrs[i] = [2]string{attr.GetKey(), attr.GetValue()} + } + return attrs +} + +// SetAttributes sets list of node attributes. +// Each attribute is a [2]string slice: {"key", "value"}. +// Both key and value of attributes MUST NOT be empty. +// +// See also SetAttribute. +func (x *NodeInfo) SetAttributes(attrs ...[2]string) { + netmapAttrs := make([]netmap.Attribute, 0, len(attrs)) + for _, attr := range attrs { + if attr[0] == "" { + panic("empty key in SetAttributes") + } else if attr[1] == "" { + panic(fmt.Errorf("empty value in SetAttributes for key: %s", attr[0])) + } + + netmapAttrs = append(netmapAttrs, netmap.Attribute{}) + netmapAttrs[len(netmapAttrs)-1].SetKey(attr[0]) + netmapAttrs[len(netmapAttrs)-1].SetValue(attr[1]) + } + + x.m.SetAttributes(netmapAttrs) +} + // SetAttribute sets value of the node attribute value by the given key. // Both key and value MUST NOT be empty. func (x *NodeInfo) SetAttribute(key, value string) { diff --git a/netmap/node_info_test.go b/netmap/node_info_test.go index 80365fa5..5bf455e9 100644 --- a/netmap/node_info_test.go +++ b/netmap/node_info_test.go @@ -294,6 +294,74 @@ func TestNodeInfo_SetContinentName(t *testing.T) { require.Equal(t, anyValidContinentName, n.ContinentName()) } +func TestNodeInfo_SetAttributes(t *testing.T) { + var n netmap.NodeInfo + require.Zero(t, n.NumberOfAttributes()) + n.IterateAttributes(func(string, string) { + t.Fatal("handler must not be called") + }) + + const k1, v1 = "k1", "v1" + const k2, v2 = "k2", "v2" + const empty = "" + + attr1 := [2]string{empty, v1} + attr2 := [2]string{k2, empty} + + require.Panics(t, func() { + n.SetAttributes(attr1) + }) + + require.Panics(t, func() { + n.SetAttributes(attr2) + }) + + attr1 = [2]string{k1, v1} + n.SetAttributes(attr1) + require.Equal(t, attr1[1], n.Attribute(k1)) + require.Equal(t, empty, n.Attribute(k2)) + require.Equal(t, 1, n.NumberOfAttributes()) + + attr2 = [2]string{k2, v2} + n.SetAttributes(attr2) + require.Equal(t, attr2[1], n.Attribute(k2)) + require.Equal(t, empty, n.Attribute(k1)) + require.Equal(t, 1, n.NumberOfAttributes()) + + n.SetAttributes(attr1, attr2) + require.Equal(t, attr1[1], n.Attribute(k1)) + require.Equal(t, attr2[1], n.Attribute(k2)) + require.Equal(t, 2, n.NumberOfAttributes()) + + n.SetAttributes() + require.Equal(t, 0, n.NumberOfAttributes()) +} + +func TestNodeInfo_GetAttributes(t *testing.T) { + var n netmap.NodeInfo + require.Zero(t, n.NumberOfAttributes()) + n.IterateAttributes(func(string, string) { + t.Fatal("handler must not be called") + }) + + const k1, v1 = "k1", "v1" + const k2, v2 = "k2", "v2" + + attr1 := [2]string{k1, v1} + attr2 := [2]string{k2, v2} + + n.SetAttributes(attr1) + attrs := n.GetAttributes() + require.Equal(t, len(attrs), n.NumberOfAttributes()) + require.Equal(t, attr1, attrs[0]) + + n.SetAttributes(attr1, attr2) + attrs = n.GetAttributes() + require.Equal(t, len(attrs), n.NumberOfAttributes()) + require.Equal(t, attr1, attrs[0]) + require.Equal(t, attr2, attrs[1]) +} + func TestNodeInfo_SetAttribute(t *testing.T) { var n netmap.NodeInfo require.Zero(t, n.NumberOfAttributes())