go.mercari.io/datastore@v1.8.2/prop_test.go (about)

     1  package datastore
     2  
     3  import (
     4  	"context"
     5  	"testing"
     6  )
     7  
     8  func TestSaveStruct_Basic(t *testing.T) {
     9  	ctx := context.Background()
    10  
    11  	type Data struct {
    12  		Str string
    13  	}
    14  
    15  	ps, err := SaveStruct(ctx, &Data{"Test"})
    16  	if err != nil {
    17  		t.Fatal(err)
    18  	}
    19  
    20  	if v := len(ps); v != 1 {
    21  		t.Fatalf("unexpected: %v", v)
    22  	}
    23  
    24  	p := ps[0]
    25  	if v := p.Name; v != "Str" {
    26  		t.Fatalf("unexpected: %v", v)
    27  	}
    28  	if v, ok := p.Value.(string); !ok {
    29  		t.Fatalf("unexpected: %v", ok)
    30  	} else if v != "Test" {
    31  		t.Fatalf("unexpected: %v", v)
    32  	}
    33  }
    34  
    35  func TestSaveStruct_Object(t *testing.T) {
    36  	ctx := context.Background()
    37  
    38  	type Data struct {
    39  		Str string
    40  	}
    41  
    42  	ps, err := SaveStruct(ctx, &Data{Str: "Str"})
    43  	if err != nil {
    44  		t.Fatal(err)
    45  	}
    46  
    47  	if v := len(ps); v != 1 {
    48  		t.Fatalf("unexpected: %v", v)
    49  	}
    50  	p := ps[0]
    51  	if v := p.Name; v != "Str" {
    52  		t.Fatalf("unexpected: %v", v)
    53  	}
    54  	if v := p.Value.(string); v != "Str" {
    55  		t.Fatalf("unexpected: %v", v)
    56  	}
    57  }
    58  
    59  func TestSaveStruct_ObjectPropertyRename(t *testing.T) {
    60  	ctx := context.Background()
    61  
    62  	type Data struct {
    63  		Str string `datastore:"modified"`
    64  	}
    65  
    66  	ps, err := SaveStruct(ctx, &Data{Str: "Str"})
    67  	if err != nil {
    68  		t.Fatal(err)
    69  	}
    70  
    71  	if v := len(ps); v != 1 {
    72  		t.Fatalf("unexpected: %v", v)
    73  	}
    74  	p := ps[0]
    75  	if v := p.Name; v != "modified" {
    76  		t.Fatalf("unexpected: %v", v)
    77  	}
    78  	if v := p.Value.(string); v != "Str" {
    79  		t.Fatalf("unexpected: %v", v)
    80  	}
    81  }
    82  
    83  func TestSaveStruct_EmbedStruct(t *testing.T) {
    84  	ctx := context.Background()
    85  
    86  	type Embed struct {
    87  		Inner string
    88  	}
    89  
    90  	type Data struct {
    91  		Embed
    92  
    93  		Str string
    94  	}
    95  
    96  	ps, err := SaveStruct(ctx, &Data{
    97  		Embed: Embed{
    98  			Inner: "Inner",
    99  		},
   100  		Str: "Str",
   101  	})
   102  	if err != nil {
   103  		t.Fatal(err)
   104  	}
   105  
   106  	if v := len(ps); v != 2 {
   107  		t.Fatalf("unexpected: %v", v)
   108  	}
   109  	{
   110  		p := ps[0]
   111  		if v := p.Name; v != "Inner" {
   112  			t.Fatalf("unexpected: %v", v)
   113  		}
   114  		if v := p.Value.(string); v != "Inner" {
   115  			t.Fatalf("unexpected: %v", v)
   116  		}
   117  	}
   118  	{
   119  		p := ps[1]
   120  		if v := p.Name; v != "Str" {
   121  			t.Fatalf("unexpected: %v", v)
   122  		}
   123  		if v := p.Value.(string); v != "Str" {
   124  			t.Fatalf("unexpected: %v", v)
   125  		}
   126  	}
   127  }
   128  
   129  func TestSaveStruct_WithEmbedPtrStruct(t *testing.T) {
   130  	ctx := context.Background()
   131  
   132  	type Inner struct {
   133  		A string
   134  		B string
   135  	}
   136  
   137  	type Data struct {
   138  		*Inner
   139  	}
   140  
   141  	{
   142  		ps, err := SaveStruct(ctx, &Data{Inner: &Inner{A: "A", B: "B"}})
   143  		if err != nil {
   144  			t.Fatal(err)
   145  		}
   146  		if v := len(ps); v != 2 {
   147  			t.Errorf("unexpected: %v", v)
   148  		}
   149  
   150  		obj := &Data{}
   151  		err = LoadStruct(ctx, obj, ps)
   152  		if err != nil {
   153  			t.Fatal(err)
   154  		}
   155  		if v := obj.Inner; v == nil {
   156  			t.Errorf("unexpected: %v", v)
   157  		}
   158  	}
   159  	{
   160  		ps, err := SaveStruct(ctx, &Data{})
   161  		if err != nil {
   162  			t.Fatal(err)
   163  		}
   164  		if v := len(ps); v != 0 {
   165  			t.Errorf("unexpected: %v", v)
   166  		}
   167  		obj := &Data{}
   168  		err = LoadStruct(ctx, obj, ps)
   169  		if err != nil {
   170  			t.Fatal(err)
   171  		}
   172  		if v := obj.Inner; v != nil {
   173  			t.Errorf("unexpected: %v", v)
   174  		}
   175  	}
   176  }
   177  
   178  func TestSaveStruct_WithPtrStruct(t *testing.T) {
   179  	// TODO Why this test is failed?
   180  	t.SkipNow()
   181  
   182  	ctx := context.Background()
   183  
   184  	type Inner struct {
   185  		A string
   186  		B string
   187  	}
   188  
   189  	type Data struct {
   190  		Inner *Inner `datastore:",flatten"`
   191  	}
   192  
   193  	{
   194  		ps, err := SaveStruct(ctx, &Data{Inner: &Inner{A: "A", B: "B"}})
   195  		if err != nil {
   196  			t.Fatal(err)
   197  		}
   198  		if v := len(ps); v != 2 {
   199  			t.Errorf("unexpected: %v", v)
   200  		}
   201  
   202  		obj := &Data{}
   203  		err = LoadStruct(ctx, obj, ps)
   204  		if err != nil {
   205  			t.Fatal(err)
   206  		}
   207  		if v := obj.Inner; v == nil {
   208  			t.Errorf("unexpected: %v", v)
   209  		}
   210  	}
   211  	{
   212  		ps, err := SaveStruct(ctx, &Data{})
   213  		if err != nil {
   214  			t.Fatal(err)
   215  		}
   216  		if v := len(ps); v != 0 {
   217  			t.Errorf("unexpected: %v", v)
   218  		}
   219  		obj := &Data{}
   220  		err = LoadStruct(ctx, obj, ps)
   221  		if err != nil {
   222  			t.Fatal(err)
   223  		}
   224  		if v := obj.Inner; v != nil {
   225  			t.Errorf("unexpected: %v", v)
   226  		}
   227  	}
   228  }
   229  
   230  func TestSaveStruct_ObjectHasObjectSlice(t *testing.T) {
   231  	ctx := context.Background()
   232  
   233  	type Inner struct {
   234  		A string
   235  		B string
   236  	}
   237  
   238  	type Data struct {
   239  		Slice []Inner
   240  	}
   241  
   242  	ps, err := SaveStruct(ctx, &Data{
   243  		Slice: []Inner{
   244  			{A: "A1", B: "B1"},
   245  			{A: "A2", B: "B2"},
   246  			{A: "A3", B: "B3"},
   247  		},
   248  	})
   249  	if err != nil {
   250  		t.Fatal(err)
   251  	}
   252  
   253  	if v := len(ps); v != 1 {
   254  		t.Fatalf("unexpected: %v", v)
   255  	}
   256  	p := ps[0]
   257  	if v := p.Name; v != "Slice" {
   258  		t.Fatalf("unexpected: %v", v)
   259  	}
   260  	es := p.Value.([]interface{})
   261  	if v := len(es); v != 3 {
   262  		t.Fatalf("unexpected: %v", v)
   263  	}
   264  
   265  	expects := []struct {
   266  		Name  string
   267  		Value string
   268  	}{
   269  		{"A", "A1"},
   270  		{"B", "B1"},
   271  		{"A", "A2"},
   272  		{"B", "B2"},
   273  		{"A", "A3"},
   274  		{"B", "B3"},
   275  	}
   276  
   277  	for idx, entity := range es {
   278  		e := entity.(*Entity)
   279  		if v := len(e.Properties); v != 2 {
   280  			t.Fatalf("unexpected: %v", v)
   281  		}
   282  		for pIdx, p := range e.Properties {
   283  			expect := expects[idx*len(e.Properties)+pIdx]
   284  			if v := p.Name; v != expect.Name {
   285  				t.Errorf("unexpected: %v", v)
   286  			}
   287  			if v := p.Value.(string); v != expect.Value {
   288  				t.Errorf("unexpected: %v", v)
   289  			}
   290  		}
   291  	}
   292  }
   293  
   294  func TestLoadStruct_Basic(t *testing.T) {
   295  	ctx := context.Background()
   296  
   297  	type Data struct {
   298  		Str string
   299  	}
   300  
   301  	var ps PropertyList
   302  	ps = append(ps, Property{
   303  		Name:  "Str",
   304  		Value: "Test",
   305  	})
   306  	obj := &Data{}
   307  	err := LoadStruct(ctx, obj, ps)
   308  	if err != nil {
   309  		t.Fatal(err)
   310  	}
   311  
   312  	if v := obj.Str; v != "Test" {
   313  		t.Fatalf("unexpected: %v", v)
   314  	}
   315  }
   316  
   317  func TestLoadStruct_IgnoreMismatchProperty(t *testing.T) {
   318  	ctx := context.Background()
   319  
   320  	type Data1 struct {
   321  		A string
   322  		B string
   323  	}
   324  	type Data2 struct {
   325  		A string
   326  	}
   327  
   328  	ps, err := SaveStruct(ctx, &Data1{})
   329  	if err != nil {
   330  		t.Fatal(err)
   331  	}
   332  
   333  	err = LoadStruct(ctx, &Data2{}, ps)
   334  	if err != nil {
   335  		t.Fatal(err)
   336  	}
   337  }
   338  
   339  func TestLoadStruct_CheckMismatchProperty(t *testing.T) {
   340  	ctx := context.Background()
   341  
   342  	SuppressErrFieldMismatch = false
   343  	defer func() {
   344  		SuppressErrFieldMismatch = true
   345  	}()
   346  
   347  	type Data1 struct {
   348  		A string
   349  		B string
   350  	}
   351  	type Data2 struct {
   352  		A string
   353  	}
   354  
   355  	ps, err := SaveStruct(ctx, &Data1{})
   356  	if err != nil {
   357  		t.Fatal(err)
   358  	}
   359  
   360  	err = LoadStruct(ctx, &Data2{}, ps)
   361  	if err == nil {
   362  		t.Fatal(err)
   363  	} else if _, ok := err.(*ErrFieldMismatch); ok {
   364  		// ok!
   365  	} else {
   366  		t.Fatal(err)
   367  	}
   368  }