github.com/authzed/spicedb@v1.32.1-0.20240520085336-ebda56537386/pkg/testutil/proto_test.go (about) 1 package testutil 2 3 import ( 4 "strings" 5 "testing" 6 7 "github.com/stretchr/testify/require" 8 "google.golang.org/protobuf/proto" 9 10 core "github.com/authzed/spicedb/pkg/proto/core/v1" 11 ) 12 13 func TestAreProtoEqual(t *testing.T) { 14 tcs := []struct { 15 name string 16 first proto.Message 17 second proto.Message 18 expectedEqual bool 19 }{ 20 { 21 "empty types", 22 &core.ObjectAndRelation{}, 23 &core.ObjectAndRelation{}, 24 true, 25 }, 26 { 27 "filled in", 28 &core.ObjectAndRelation{ 29 Namespace: "foo", 30 }, 31 &core.ObjectAndRelation{ 32 Namespace: "foo", 33 }, 34 true, 35 }, 36 { 37 "nested", 38 &core.RelationTuple{ 39 ResourceAndRelation: &core.ObjectAndRelation{ 40 Namespace: "foo", 41 }, 42 }, 43 &core.RelationTuple{ 44 ResourceAndRelation: &core.ObjectAndRelation{ 45 Namespace: "foo", 46 }, 47 }, 48 true, 49 }, 50 { 51 "nested difference", 52 &core.RelationTuple{ 53 ResourceAndRelation: &core.ObjectAndRelation{ 54 Namespace: "foo", 55 }, 56 }, 57 &core.RelationTuple{ 58 ResourceAndRelation: &core.ObjectAndRelation{ 59 Namespace: "bar", 60 }, 61 }, 62 false, 63 }, 64 { 65 "empty slice vs nil", 66 &core.CaveatTypeReference{ 67 TypeName: "test", 68 ChildTypes: []*core.CaveatTypeReference{}, 69 }, 70 &core.CaveatTypeReference{ 71 TypeName: "test", 72 ChildTypes: nil, 73 }, 74 true, 75 }, 76 { 77 "element diff", 78 &core.CaveatTypeReference{ 79 TypeName: "test", 80 ChildTypes: []*core.CaveatTypeReference{ 81 { 82 TypeName: "foo", 83 }, 84 }, 85 }, 86 &core.CaveatTypeReference{ 87 TypeName: "test", 88 ChildTypes: []*core.CaveatTypeReference{ 89 { 90 TypeName: "bar", 91 }, 92 }, 93 }, 94 false, 95 }, 96 } 97 98 for _, tc := range tcs { 99 tc := tc 100 t.Run(tc.name, func(t *testing.T) { 101 err := AreProtoEqual(tc.first, tc.second, "something went wrong") 102 require.True(t, (err == nil) == (tc.expectedEqual)) 103 }) 104 } 105 } 106 107 func TestRequireProtoEqual(t *testing.T) { 108 tcs := []struct { 109 name string 110 first proto.Message 111 second proto.Message 112 }{ 113 { 114 "empty types", 115 &core.ObjectAndRelation{}, 116 &core.ObjectAndRelation{}, 117 }, 118 { 119 "filled in", 120 &core.ObjectAndRelation{ 121 Namespace: "foo", 122 }, 123 &core.ObjectAndRelation{ 124 Namespace: "foo", 125 }, 126 }, 127 { 128 "nested", 129 &core.RelationTuple{ 130 ResourceAndRelation: &core.ObjectAndRelation{ 131 Namespace: "foo", 132 }, 133 }, 134 &core.RelationTuple{ 135 ResourceAndRelation: &core.ObjectAndRelation{ 136 Namespace: "foo", 137 }, 138 }, 139 }, 140 { 141 "empty slice vs nil", 142 &core.CaveatTypeReference{ 143 TypeName: "test", 144 ChildTypes: []*core.CaveatTypeReference{}, 145 }, 146 &core.CaveatTypeReference{ 147 TypeName: "test", 148 ChildTypes: nil, 149 }, 150 }, 151 } 152 153 for _, tc := range tcs { 154 tc := tc 155 t.Run(tc.name, func(t *testing.T) { 156 RequireProtoEqual(t, tc.first, tc.second, "something went wrong") 157 }) 158 } 159 } 160 161 func TestAreProtoSlicesEqual(t *testing.T) { 162 tcs := []struct { 163 name string 164 first []*core.ObjectAndRelation 165 second []*core.ObjectAndRelation 166 expectedEqual bool 167 }{ 168 { 169 "empty slices", 170 []*core.ObjectAndRelation{}, 171 []*core.ObjectAndRelation{}, 172 true, 173 }, 174 { 175 "ordered slices", 176 []*core.ObjectAndRelation{ 177 {Namespace: "document", ObjectId: "first", Relation: "viewer"}, 178 {Namespace: "document", ObjectId: "second", Relation: "viewer"}, 179 }, 180 []*core.ObjectAndRelation{ 181 {Namespace: "document", ObjectId: "first", Relation: "viewer"}, 182 {Namespace: "document", ObjectId: "second", Relation: "viewer"}, 183 }, 184 true, 185 }, 186 { 187 "unordered slices", 188 []*core.ObjectAndRelation{ 189 {Namespace: "document", ObjectId: "first", Relation: "viewer"}, 190 {Namespace: "document", ObjectId: "second", Relation: "viewer"}, 191 }, 192 []*core.ObjectAndRelation{ 193 {Namespace: "document", ObjectId: "second", Relation: "viewer"}, 194 {Namespace: "document", ObjectId: "first", Relation: "viewer"}, 195 }, 196 true, 197 }, 198 { 199 "different slices", 200 []*core.ObjectAndRelation{ 201 {Namespace: "document", ObjectId: "first", Relation: "viewer"}, 202 {Namespace: "document", ObjectId: "second", Relation: "viewer"}, 203 }, 204 []*core.ObjectAndRelation{ 205 {Namespace: "document", ObjectId: "second", Relation: "viewer"}, 206 }, 207 false, 208 }, 209 { 210 "different slice values", 211 []*core.ObjectAndRelation{ 212 {Namespace: "document", ObjectId: "first", Relation: "viewer"}, 213 }, 214 []*core.ObjectAndRelation{ 215 {Namespace: "document", ObjectId: "second", Relation: "viewer"}, 216 }, 217 false, 218 }, 219 } 220 221 for _, tc := range tcs { 222 tc := tc 223 t.Run(tc.name, func(t *testing.T) { 224 err := AreProtoSlicesEqual(tc.first, tc.second, func(first, second *core.ObjectAndRelation) int { 225 return strings.Compare(first.ObjectId, second.ObjectId) 226 }, "something went wrong") 227 require.True(t, (err == nil) == (tc.expectedEqual)) 228 }) 229 } 230 } 231 232 func TestRequireProtoSlicesEqual(t *testing.T) { 233 tcs := []struct { 234 name string 235 first []*core.ObjectAndRelation 236 second []*core.ObjectAndRelation 237 }{ 238 { 239 "empty slices", 240 []*core.ObjectAndRelation{}, 241 []*core.ObjectAndRelation{}, 242 }, 243 { 244 "ordered slices", 245 []*core.ObjectAndRelation{ 246 {Namespace: "document", ObjectId: "first", Relation: "viewer"}, 247 {Namespace: "document", ObjectId: "second", Relation: "viewer"}, 248 }, 249 []*core.ObjectAndRelation{ 250 {Namespace: "document", ObjectId: "first", Relation: "viewer"}, 251 {Namespace: "document", ObjectId: "second", Relation: "viewer"}, 252 }, 253 }, 254 { 255 "unordered slices", 256 []*core.ObjectAndRelation{ 257 {Namespace: "document", ObjectId: "first", Relation: "viewer"}, 258 {Namespace: "document", ObjectId: "second", Relation: "viewer"}, 259 }, 260 []*core.ObjectAndRelation{ 261 {Namespace: "document", ObjectId: "second", Relation: "viewer"}, 262 {Namespace: "document", ObjectId: "first", Relation: "viewer"}, 263 }, 264 }, 265 } 266 267 for _, tc := range tcs { 268 tc := tc 269 t.Run(tc.name, func(t *testing.T) { 270 RequireProtoSlicesEqual(t, tc.first, tc.second, func(first *core.ObjectAndRelation, second *core.ObjectAndRelation) int { 271 return strings.Compare(first.ObjectId, second.ObjectId) 272 }, "something went wrong") 273 }) 274 } 275 }