github.com/litesolutions/justifay-api@v1.0.0-2.0.20220707114139-46f28a909481/internal/pkg/structs/merge_test.go (about)

     1  package structs_test
     2  
     3  import (
     4  	"testing"
     5  
     6  	"github.com/litesolutions/justifay-api/internal/pkg/structs"
     7  	"github.com/stretchr/testify/assert"
     8  )
     9  
    10  type carID int64
    11  
    12  type mergeStruct struct {
    13  	Name              string
    14  	Surname           string
    15  	SomeID            int64
    16  	Cars              []string
    17  	CarIDs            []carID
    18  	CustomStruct      customStruct
    19  	CustomStructSlice []customStruct
    20  	IgnoredField      string
    21  	PointerField      *string
    22  	SkipField         map[string]string
    23  }
    24  
    25  type customStruct struct {
    26  	isLoved bool
    27  	isHated bool
    28  }
    29  
    30  type mergeCmd struct {
    31  	Name              *string
    32  	Surname           *string
    33  	SomeID            *int64
    34  	Cars              []string
    35  	CarIDs            []carID
    36  	CustomStruct      *customStruct
    37  	CustomStructSlice []customStruct
    38  	IgnoredField      *string `structs:"-"`
    39  	PointerField      *string
    40  	SkipField         map[string]string
    41  }
    42  
    43  func TestMerge(t *testing.T) {
    44  	cases := map[string]struct {
    45  		mstruct      mergeStruct
    46  		cmd          func() mergeCmd
    47  		mergedStruct mergeStruct
    48  		notPointer   bool
    49  	}{
    50  		"basic merge": {
    51  			mstruct: mergeStruct{
    52  				Name: "Name",
    53  			},
    54  			cmd: func() mergeCmd {
    55  				surname := "Surname"
    56  				return mergeCmd{
    57  					Surname: &surname,
    58  				}
    59  			},
    60  			mergedStruct: mergeStruct{
    61  				Name:    "Name",
    62  				Surname: "Surname",
    63  			},
    64  		},
    65  		"not a pointer": {
    66  			mstruct: mergeStruct{
    67  				Name: "Name",
    68  			},
    69  			cmd: func() mergeCmd {
    70  				surname := "Surname"
    71  				return mergeCmd{
    72  					Surname: &surname,
    73  				}
    74  			},
    75  			mergedStruct: mergeStruct{
    76  				Name:    "Name",
    77  				Surname: "Surname",
    78  			},
    79  			notPointer: true,
    80  		},
    81  		"skipping field": {
    82  			mstruct: mergeStruct{
    83  				Name: "Name",
    84  			},
    85  			cmd: func() mergeCmd {
    86  				surname := "Surname"
    87  
    88  				return mergeCmd{
    89  					Surname: &surname,
    90  					SkipField: map[string]string{
    91  						"name": "surname",
    92  					},
    93  				}
    94  			},
    95  			mergedStruct: mergeStruct{
    96  				Name:    "Name",
    97  				Surname: "Surname",
    98  			},
    99  		},
   100  		"pointer field": {
   101  			mstruct: mergeStruct{
   102  				Name:         "Name",
   103  				PointerField: ptrString("Pointer"),
   104  			},
   105  			cmd: func() mergeCmd {
   106  				surname := "Surname"
   107  				ptrField := "Pointer"
   108  
   109  				return mergeCmd{
   110  					Surname:      &surname,
   111  					PointerField: &ptrField,
   112  				}
   113  			},
   114  			mergedStruct: mergeStruct{
   115  				Name:         "Name",
   116  				Surname:      "Surname",
   117  				PointerField: ptrString("Pointer"),
   118  			},
   119  		},
   120  		"basic slice merge": {
   121  			mstruct: mergeStruct{
   122  				Name: "Dz",
   123  			},
   124  			cmd: func() mergeCmd {
   125  				surname := "G"
   126  				return mergeCmd{
   127  					Surname: &surname,
   128  					Cars:    []string{"peugeot", "citroen"},
   129  				}
   130  			},
   131  			mergedStruct: mergeStruct{
   132  				Name:    "Dz",
   133  				Surname: "G",
   134  				Cars:    []string{"peugeot", "citroen"},
   135  			},
   136  		},
   137  		"custom slice merge": {
   138  			mstruct: mergeStruct{
   139  				Name: "Dz",
   140  			},
   141  			cmd: func() mergeCmd {
   142  				surname := "G"
   143  				return mergeCmd{
   144  					Surname: &surname,
   145  					Cars:    []string{"peugeot", "citroen"},
   146  					CarIDs:  []carID{1, 2},
   147  				}
   148  			},
   149  			mergedStruct: mergeStruct{
   150  				Name:    "Dz",
   151  				Surname: "G",
   152  				Cars:    []string{"peugeot", "citroen"},
   153  				CarIDs:  []carID{1, 2},
   154  			},
   155  		},
   156  		"merge slice": {
   157  			mstruct: mergeStruct{
   158  				Name:   "Name",
   159  				SomeID: 5,
   160  				CarIDs: []carID{1, 2, 3},
   161  			},
   162  			cmd: func() mergeCmd {
   163  				surname := "Surname"
   164  				someID := int64(3)
   165  				return mergeCmd{
   166  					Surname: &surname,
   167  					SomeID:  &someID,
   168  					CarIDs:  []carID{6, 7, 8},
   169  				}
   170  			},
   171  			mergedStruct: mergeStruct{
   172  				Name:    "Name",
   173  				Surname: "Surname",
   174  				SomeID:  3,
   175  				CarIDs:  []carID{6, 7, 8},
   176  			},
   177  		},
   178  		"test ignored fields": {
   179  			mstruct: mergeStruct{
   180  				Name:         "Name",
   181  				SomeID:       5,
   182  				IgnoredField: "ignored",
   183  				CarIDs:       []carID{1, 2, 3},
   184  			},
   185  			cmd: func() mergeCmd {
   186  				surname := "Surname"
   187  				someID := int64(3)
   188  				ignored := "ignored-update"
   189  				return mergeCmd{
   190  					Surname:      &surname,
   191  					SomeID:       &someID,
   192  					IgnoredField: &ignored,
   193  					CarIDs:       []carID{6, 7, 8},
   194  				}
   195  			},
   196  			mergedStruct: mergeStruct{
   197  				Name:         "Name",
   198  				Surname:      "Surname",
   199  				SomeID:       3,
   200  				IgnoredField: "ignored",
   201  				CarIDs:       []carID{6, 7, 8},
   202  			},
   203  		},
   204  		"custom struct merge": {
   205  			mstruct: mergeStruct{
   206  				Name:         "Name",
   207  				SomeID:       5,
   208  				IgnoredField: "ignored",
   209  				CarIDs:       []carID{1, 2, 3},
   210  				CustomStruct: customStruct{
   211  					isLoved: true,
   212  					isHated: false,
   213  				},
   214  			},
   215  			cmd: func() mergeCmd {
   216  				surname := "Surname"
   217  				someID := int64(3)
   218  				ignored := "ignored-update"
   219  				return mergeCmd{
   220  					Surname:      &surname,
   221  					SomeID:       &someID,
   222  					IgnoredField: &ignored,
   223  					CarIDs:       []carID{6, 7, 8},
   224  					CustomStruct: &customStruct{
   225  						isLoved: false,
   226  						isHated: false,
   227  					},
   228  				}
   229  			},
   230  			mergedStruct: mergeStruct{
   231  				Name:         "Name",
   232  				Surname:      "Surname",
   233  				SomeID:       3,
   234  				IgnoredField: "ignored",
   235  				CarIDs:       []carID{6, 7, 8},
   236  				CustomStruct: customStruct{
   237  					isLoved: false,
   238  					isHated: false,
   239  				},
   240  			},
   241  		},
   242  		"custom struct slice merge": {
   243  			mstruct: mergeStruct{
   244  				Name:         "Name",
   245  				SomeID:       5,
   246  				IgnoredField: "ignored",
   247  				CarIDs:       []carID{1, 2, 3},
   248  				CustomStructSlice: []customStruct{
   249  					{
   250  						isLoved: true,
   251  						isHated: true,
   252  					},
   253  					{
   254  						isLoved: false,
   255  						isHated: false,
   256  					},
   257  				},
   258  			},
   259  			cmd: func() mergeCmd {
   260  				surname := "Surname"
   261  				someID := int64(3)
   262  				ignored := "ignored-update"
   263  				return mergeCmd{
   264  					Surname:      &surname,
   265  					SomeID:       &someID,
   266  					IgnoredField: &ignored,
   267  					CarIDs:       []carID{6, 7, 8},
   268  					CustomStructSlice: []customStruct{
   269  						{
   270  							isLoved: false,
   271  							isHated: true,
   272  						},
   273  					},
   274  				}
   275  			},
   276  			mergedStruct: mergeStruct{
   277  				Name:         "Name",
   278  				Surname:      "Surname",
   279  				SomeID:       3,
   280  				IgnoredField: "ignored",
   281  				CarIDs:       []carID{6, 7, 8},
   282  				CustomStructSlice: []customStruct{
   283  					{
   284  						isLoved: false,
   285  						isHated: true,
   286  					},
   287  				},
   288  			},
   289  		},
   290  		"nil struct merge": {
   291  			mstruct: mergeStruct{
   292  				Name:         "Name",
   293  				SomeID:       5,
   294  				IgnoredField: "ignored",
   295  				CarIDs:       []carID{1, 2, 3},
   296  			},
   297  			cmd: func() mergeCmd {
   298  				surname := "Surname"
   299  				someID := int64(3)
   300  				ignored := "ignored-update"
   301  				return mergeCmd{
   302  					Surname:      &surname,
   303  					SomeID:       &someID,
   304  					IgnoredField: &ignored,
   305  					CarIDs:       []carID{6, 7, 8},
   306  					CustomStruct: nil,
   307  				}
   308  			},
   309  			mergedStruct: mergeStruct{
   310  				Name:         "Name",
   311  				Surname:      "Surname",
   312  				SomeID:       3,
   313  				IgnoredField: "ignored",
   314  				CarIDs:       []carID{6, 7, 8},
   315  			},
   316  		},
   317  		"empty slice merge": {
   318  			mstruct: mergeStruct{
   319  				Name:         "Name",
   320  				SomeID:       5,
   321  				IgnoredField: "ignored",
   322  				CarIDs:       []carID{1, 2, 3},
   323  			},
   324  			cmd: func() mergeCmd {
   325  				surname := "Surname"
   326  				someID := int64(3)
   327  				ignored := "ignored-update"
   328  				return mergeCmd{
   329  					Surname:           &surname,
   330  					SomeID:            &someID,
   331  					IgnoredField:      &ignored,
   332  					CarIDs:            []carID{6, 7, 8},
   333  					CustomStructSlice: []customStruct{},
   334  				}
   335  			},
   336  			mergedStruct: mergeStruct{
   337  				Name:              "Name",
   338  				Surname:           "Surname",
   339  				SomeID:            3,
   340  				IgnoredField:      "ignored",
   341  				CarIDs:            []carID{6, 7, 8},
   342  				CustomStructSlice: []customStruct{},
   343  			},
   344  		},
   345  	}
   346  	for name, c := range cases {
   347  		t.Run(name, func(t *testing.T) {
   348  			cmd := c.cmd()
   349  			if c.notPointer {
   350  				structs.Merge(c.mstruct, &cmd)
   351  				assert.NotEqual(t, c.mstruct, c.mergedStruct)
   352  				return
   353  			}
   354  			structs.Merge(&c.mstruct, &cmd)
   355  			assert.Equal(t, c.mstruct, c.mergedStruct)
   356  		})
   357  	}
   358  }
   359  
   360  func ptrString(s string) *string {
   361  	return &s
   362  }