git.frostfs.info/TrueCloudLab/frostfs-sdk-go@v0.0.0-20241022124111-5361f0ecebd3/ns/nns_test.go (about) 1 package ns 2 3 import ( 4 "crypto/rand" 5 "errors" 6 "fmt" 7 "math/big" 8 "strings" 9 "testing" 10 11 "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container" 12 cidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id/test" 13 "github.com/nspcc-dev/neo-go/pkg/neorpc/result" 14 "github.com/nspcc-dev/neo-go/pkg/util" 15 "github.com/nspcc-dev/neo-go/pkg/vm/stackitem" 16 "github.com/nspcc-dev/neo-go/pkg/vm/vmstate" 17 "github.com/stretchr/testify/require" 18 ) 19 20 // testNeoClient represents test Neo client which checks invocation arguments 21 // and returns predefined result. 22 type testNeoClient struct { 23 t *testing.T 24 25 expectedContract util.Uint160 26 27 res result.Invoke 28 29 err error 30 } 31 32 func (x *testNeoClient) Call(contract util.Uint160, operation string, params ...any) (*result.Invoke, error) { 33 var domain string 34 35 require.Equal(x.t, x.expectedContract, contract) 36 require.Equal(x.t, "resolve", operation) 37 require.Len(x.t, params, 2) 38 require.NotPanics(x.t, func() { domain = params[0].(string) }) 39 require.NotPanics(x.t, func() { _ = params[1].(int64) }) 40 require.True(x.t, strings.HasSuffix(domain, ".container")) 41 require.NotEmpty(x.t, strings.TrimSuffix(domain, ".container")) 42 43 return &x.res, x.err 44 } 45 46 // implements test stackitem.Item which is obviously incorrect: 47 // it returns itself on Convert(stackitem.ArrayT), but returns integer from Value. 48 type brokenArrayStackItem struct { 49 stackitem.Item 50 } 51 52 func (x brokenArrayStackItem) Value() any { 53 return 1 54 } 55 56 func (x brokenArrayStackItem) Convert(t stackitem.Type) (stackitem.Item, error) { 57 if t != stackitem.ArrayT { 58 panic(fmt.Sprintf("unexpected stack item type %s", t)) 59 } 60 61 return x, nil 62 } 63 64 func TestNNS_ResolveContainerDomain(t *testing.T) { 65 var testContainerDomain container.Domain 66 testContainerDomain.SetName("some_container") 67 68 var nnsContract util.Uint160 69 70 rand.Read(nnsContract[:]) 71 72 testC := &testNeoClient{ 73 t: t, 74 expectedContract: nnsContract, 75 } 76 77 n := NNS{ 78 nnsContract: nnsContract, 79 invoker: testC, 80 } 81 82 t.Run("invocation failure", func(t *testing.T) { 83 err1 := errors.New("invoke err") 84 testC.err = err1 85 86 _, err2 := n.ResolveContainerDomain(testContainerDomain) 87 require.ErrorIs(t, err2, err1) 88 }) 89 90 testC.err = nil 91 92 t.Run("fault exception", func(t *testing.T) { 93 _, err := n.ResolveContainerDomain(testContainerDomain) 94 require.Error(t, err) 95 }) 96 97 testC.res.State = vmstate.Halt.String() 98 99 t.Run("empty stack", func(t *testing.T) { 100 _, err := n.ResolveContainerDomain(testContainerDomain) 101 require.Error(t, err) 102 }) 103 104 testC.res.Stack = make([]stackitem.Item, 1) 105 106 t.Run("non-array last stack item", func(t *testing.T) { 107 testC.res.Stack[0] = stackitem.NewBigInteger(big.NewInt(11)) 108 109 _, err := n.ResolveContainerDomain(testContainerDomain) 110 require.Error(t, err) 111 }) 112 113 t.Run("null array", func(t *testing.T) { 114 testC.res.Stack[0] = stackitem.Null{} 115 116 _, err := n.ResolveContainerDomain(testContainerDomain) 117 require.ErrorIs(t, err, errNotFound) 118 }) 119 120 t.Run("array stack item with non-slice value", func(t *testing.T) { 121 testC.res.Stack[0] = brokenArrayStackItem{} 122 123 _, err := n.ResolveContainerDomain(testContainerDomain) 124 require.Error(t, err) 125 }) 126 127 arr := make([]stackitem.Item, 2) 128 testC.res.Stack[0] = stackitem.NewArray(arr) 129 130 t.Run("non-bytes array element", func(t *testing.T) { 131 arr[0] = stackitem.NewArray(nil) 132 133 _, err := n.ResolveContainerDomain(testContainerDomain) 134 require.Error(t, err) 135 }) 136 137 arr[0] = stackitem.NewByteArray([]byte("some byte array 1")) 138 139 t.Run("non-container array elements", func(t *testing.T) { 140 arr[1] = stackitem.NewByteArray([]byte("some byte array 2")) 141 142 _, err := n.ResolveContainerDomain(testContainerDomain) 143 require.Error(t, err) 144 }) 145 146 t.Run("with container array element", func(t *testing.T) { 147 id := cidtest.ID() 148 149 arr[1] = stackitem.NewByteArray([]byte(id.EncodeToString())) 150 151 res, err := n.ResolveContainerDomain(testContainerDomain) 152 require.NoError(t, err) 153 154 require.Equal(t, id, res) 155 }) 156 } 157 158 func TestNNS_ResolveContractHash(t *testing.T) { 159 var testContainerDomain container.Domain 160 testContainerDomain.SetName("some_container") 161 162 var nnsContract util.Uint160 163 164 rand.Read(nnsContract[:]) 165 166 testC := &testNeoClient{ 167 t: t, 168 expectedContract: nnsContract, 169 } 170 171 n := NNS{ 172 nnsContract: nnsContract, 173 invoker: testC, 174 } 175 176 t.Run("invocation failure", func(t *testing.T) { 177 err1 := errors.New("invoke err") 178 testC.err = err1 179 180 _, err2 := n.ResolveContractHash(testContainerDomain) 181 require.ErrorIs(t, err2, err1) 182 }) 183 184 testC.err = nil 185 186 t.Run("fault exception", func(t *testing.T) { 187 _, err := n.ResolveContractHash(testContainerDomain) 188 require.Error(t, err) 189 }) 190 191 testC.res.State = vmstate.Halt.String() 192 193 t.Run("empty stack", func(t *testing.T) { 194 _, err := n.ResolveContractHash(testContainerDomain) 195 require.Error(t, err) 196 }) 197 198 testC.res.Stack = make([]stackitem.Item, 1) 199 200 t.Run("non-array last stack item", func(t *testing.T) { 201 testC.res.Stack[0] = stackitem.NewBigInteger(big.NewInt(11)) 202 203 _, err := n.ResolveContractHash(testContainerDomain) 204 require.Error(t, err) 205 }) 206 207 t.Run("null array", func(t *testing.T) { 208 testC.res.Stack[0] = stackitem.Null{} 209 210 _, err := n.ResolveContractHash(testContainerDomain) 211 require.ErrorIs(t, err, errNotFound) 212 }) 213 214 t.Run("array stack item with non-slice value", func(t *testing.T) { 215 testC.res.Stack[0] = brokenArrayStackItem{} 216 217 _, err := n.ResolveContractHash(testContainerDomain) 218 require.Error(t, err) 219 }) 220 221 arr := make([]stackitem.Item, 2) 222 testC.res.Stack[0] = stackitem.NewArray(arr) 223 224 t.Run("non-bytes array element", func(t *testing.T) { 225 arr[0] = stackitem.NewArray(nil) 226 227 _, err := n.ResolveContractHash(testContainerDomain) 228 require.Error(t, err) 229 }) 230 231 arr[0] = stackitem.NewByteArray([]byte("some byte array 1")) 232 233 t.Run("non-container array elements", func(t *testing.T) { 234 arr[1] = stackitem.NewByteArray([]byte("some byte array 2")) 235 236 _, err := n.ResolveContractHash(testContainerDomain) 237 require.Error(t, err) 238 }) 239 }