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  }