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

     1  package testbed
     2  
     3  import (
     4  	"context"
     5  	"errors"
     6  	"fmt"
     7  	"os"
     8  	"sort"
     9  	"strings"
    10  	"testing"
    11  
    12  	"github.com/favclip/testerator/v2"
    13  	_ "github.com/favclip/testerator/v2/datastore"
    14  	_ "github.com/favclip/testerator/v2/memcache"
    15  
    16  	netcontext "golang.org/x/net/context"
    17  	"google.golang.org/appengine"
    18  	"google.golang.org/appengine/datastore"
    19  )
    20  
    21  type AEDatastoreStruct struct {
    22  	Test string
    23  }
    24  
    25  func TestMain(m *testing.M) {
    26  	_, _, err := testerator.SpinUp()
    27  	if err != nil {
    28  		fmt.Fprint(os.Stderr, err.Error())
    29  		os.Exit(1)
    30  	}
    31  
    32  	status := m.Run()
    33  
    34  	err = testerator.SpinDown()
    35  	if err != nil {
    36  		fmt.Fprint(os.Stderr, err.Error())
    37  		os.Exit(1)
    38  	}
    39  
    40  	os.Exit(status)
    41  }
    42  
    43  func newContext() (context.Context, func(), error) {
    44  	_, ctx, err := testerator.SpinUp()
    45  	if err != nil {
    46  		return nil, nil, err
    47  	}
    48  
    49  	return ctx, func() { testerator.SpinDown() }, nil
    50  }
    51  
    52  func TestAEDatastore_Put(t *testing.T) {
    53  	ctx, close, err := newContext()
    54  	if err != nil {
    55  		t.Fatal(err)
    56  	}
    57  	defer close()
    58  
    59  	key := datastore.NewIncompleteKey(ctx, "AEDatastoreStruct", nil)
    60  	key, err = datastore.Put(ctx, key, &AEDatastoreStruct{"Hi!"})
    61  	if err != nil {
    62  		t.Fatal(err.Error())
    63  	}
    64  
    65  	t.Logf("key: %s", key.String())
    66  }
    67  
    68  func TestAEDatastore_GetMulti(t *testing.T) {
    69  	ctx, close, err := newContext()
    70  	if err != nil {
    71  		t.Fatal(err)
    72  	}
    73  	defer close()
    74  
    75  	type Data struct {
    76  		Str string
    77  	}
    78  
    79  	key1, err := datastore.Put(ctx, datastore.NewKey(ctx, "Data", "", 1, nil), &Data{"Data1"})
    80  	if err != nil {
    81  		t.Fatal(err.Error())
    82  	}
    83  	key2, err := datastore.Put(ctx, datastore.NewKey(ctx, "Data", "", 2, nil), &Data{"Data2"})
    84  	if err != nil {
    85  		t.Fatal(err.Error())
    86  	}
    87  
    88  	list := make([]*Data, 2)
    89  	err = datastore.GetMulti(ctx, []*datastore.Key{key1, key2}, list)
    90  	if err != nil {
    91  		t.Fatal(err.Error())
    92  	}
    93  
    94  	if v := len(list); v != 2 {
    95  		t.Fatalf("unexpected: %v", v)
    96  	}
    97  }
    98  
    99  func TestAEDatastore_Transaction(t *testing.T) {
   100  	ctx, close, err := newContext()
   101  	if err != nil {
   102  		t.Fatal(err)
   103  	}
   104  	defer close()
   105  
   106  	key := datastore.NewIncompleteKey(ctx, "AEDatastoreStruct", nil)
   107  	key, err = datastore.Put(ctx, key, &AEDatastoreStruct{"Hi!"})
   108  	if err != nil {
   109  		t.Fatal(err.Error())
   110  	}
   111  
   112  	newTransaction := func(ctx context.Context) (context.Context, func() error, func() error) {
   113  		if ctx == nil {
   114  			t.Fatal("context is not coming")
   115  		}
   116  
   117  		ctxC := make(chan context.Context)
   118  
   119  		type transaction struct {
   120  			commit   bool
   121  			rollback bool
   122  		}
   123  
   124  		finishC := make(chan transaction)
   125  		resultC := make(chan error)
   126  
   127  		commit := func() error {
   128  			finishC <- transaction{commit: true}
   129  			return <-resultC
   130  		}
   131  		rollback := func() error {
   132  			finishC <- transaction{rollback: true}
   133  			return <-resultC
   134  		}
   135  		rollbackErr := errors.New("rollback requested")
   136  
   137  		go func() {
   138  			err := datastore.RunInTransaction(ctx, func(ctx netcontext.Context) error {
   139  				t.Logf("into datastore.RunInTransaction")
   140  
   141  				ctxC <- ctx
   142  
   143  				t.Logf("send context")
   144  
   145  				result, ok := <-finishC
   146  				t.Logf("receive action: %v, %+v", ok, result)
   147  				if !ok {
   148  					return errors.New("channel closed")
   149  				}
   150  				if result.commit {
   151  					return nil
   152  				} else if result.rollback {
   153  					return rollbackErr
   154  				}
   155  
   156  				panic("unexpected state")
   157  
   158  			}, &datastore.TransactionOptions{XG: true})
   159  			if err == rollbackErr {
   160  				// This is intended error
   161  				err = nil
   162  			}
   163  			resultC <- err
   164  		}()
   165  
   166  		ctx = <-ctxC
   167  
   168  		return ctx, commit, rollback
   169  	}
   170  
   171  	{ // Commit
   172  		txCtx, commit, _ := newTransaction(ctx)
   173  
   174  		s := &AEDatastoreStruct{}
   175  		err = datastore.Get(txCtx, key, s)
   176  		if err != nil {
   177  			t.Fatal(err.Error())
   178  		}
   179  
   180  		s.Test = "Updated 1"
   181  		_, err := datastore.Put(txCtx, key, s)
   182  		if err != nil {
   183  			t.Fatal(err.Error())
   184  		}
   185  
   186  		err = commit()
   187  		if err != nil {
   188  			t.Fatal(err.Error())
   189  		}
   190  
   191  		// should updated
   192  		newS := &AEDatastoreStruct{}
   193  		err = datastore.Get(ctx, key, newS)
   194  		if err != nil {
   195  			t.Fatal(err.Error())
   196  		}
   197  
   198  		if v := newS.Test; v != "Updated 1" {
   199  			t.Fatalf("unexpected: %+v", v)
   200  		}
   201  	}
   202  	{ // Rollback
   203  		txCtx, _, rollback := newTransaction(ctx)
   204  
   205  		s := &AEDatastoreStruct{}
   206  		err = datastore.Get(txCtx, key, s)
   207  		if err != nil {
   208  			t.Fatal(err.Error())
   209  		}
   210  
   211  		s.Test = "Updated 2"
   212  		_, err := datastore.Put(txCtx, key, s)
   213  		if err != nil {
   214  			t.Fatal(err.Error())
   215  		}
   216  
   217  		err = rollback()
   218  		if err != nil {
   219  			t.Fatal(err.Error())
   220  		}
   221  
   222  		// should not updated
   223  		newS := &AEDatastoreStruct{}
   224  		err = datastore.Get(ctx, key, newS)
   225  		if err != nil {
   226  			t.Fatal(err.Error())
   227  		}
   228  
   229  		if v := newS.Test; v != "Updated 1" {
   230  			t.Fatalf("unexpected: %+v", v)
   231  		}
   232  	}
   233  
   234  	t.Logf("key: %s", key.String())
   235  }
   236  
   237  func TestAEDatastore_TransactionDeleteAndGet(t *testing.T) {
   238  	ctx, close, err := newContext()
   239  	if err != nil {
   240  		t.Fatal(err)
   241  	}
   242  	defer close()
   243  
   244  	type Data struct {
   245  		Str string
   246  	}
   247  
   248  	key, err := datastore.Put(ctx, datastore.NewIncompleteKey(ctx, "Data", nil), &Data{"Data"})
   249  	if err != nil {
   250  		t.Fatal(err.Error())
   251  	}
   252  
   253  	err = datastore.RunInTransaction(ctx, func(ctx netcontext.Context) error {
   254  		err := datastore.Delete(ctx, key)
   255  		if err != nil {
   256  			return err
   257  		}
   258  
   259  		obj := &Data{}
   260  		err = datastore.Get(ctx, key, obj)
   261  		if err != nil {
   262  			t.Fatalf("unexpected: %v", err)
   263  		}
   264  
   265  		return nil
   266  	}, nil)
   267  
   268  	if err != nil {
   269  		t.Fatal(err.Error())
   270  	}
   271  }
   272  
   273  func TestAEDatastore_Query(t *testing.T) {
   274  	ctx, close, err := newContext()
   275  	if err != nil {
   276  		t.Fatal(err)
   277  	}
   278  	defer close()
   279  
   280  	type Data struct {
   281  		Str string
   282  	}
   283  
   284  	_, err = datastore.Put(ctx, datastore.NewIncompleteKey(ctx, "Data", nil), &Data{"Data1"})
   285  	if err != nil {
   286  		t.Fatal(err.Error())
   287  	}
   288  	_, err = datastore.Put(ctx, datastore.NewIncompleteKey(ctx, "Data", nil), &Data{"Data2"})
   289  	if err != nil {
   290  		t.Fatal(err.Error())
   291  	}
   292  
   293  	q := datastore.NewQuery("Data").Filter("Str =", "Data2")
   294  	{
   295  		var list []*Data
   296  		_, err = q.GetAll(ctx, &list)
   297  		if err != nil {
   298  			t.Fatal(err.Error())
   299  		}
   300  
   301  		if v := len(list); v != 1 {
   302  			t.Fatalf("unexpected: %v", v)
   303  		}
   304  	}
   305  	{
   306  		keys, err := q.KeysOnly().GetAll(ctx, nil)
   307  		if err != nil {
   308  			t.Fatal(err.Error())
   309  		}
   310  
   311  		if v := len(keys); v != 1 {
   312  			t.Fatalf("unexpected: %v", v)
   313  		}
   314  	}
   315  }
   316  
   317  func TestAEDatastore_QueryCursor(t *testing.T) {
   318  	ctx, close, err := newContext()
   319  	if err != nil {
   320  		t.Fatal(err)
   321  	}
   322  	defer close()
   323  
   324  	type Data struct {
   325  		Str string
   326  	}
   327  
   328  	{
   329  		var keys []*datastore.Key
   330  		var entities []*Data
   331  		for i := 0; i < 100; i++ {
   332  			keys = append(keys, datastore.NewIncompleteKey(ctx, "Data", nil))
   333  			entities = append(entities, &Data{Str: fmt.Sprintf("#%d", i+1)})
   334  		}
   335  		_, err = datastore.PutMulti(ctx, keys, entities)
   336  		if err != nil {
   337  			t.Fatal(err)
   338  		}
   339  	}
   340  
   341  	var cur datastore.Cursor
   342  	var dataList []*Data
   343  	const limit = 3
   344  outer:
   345  	for {
   346  		q := datastore.NewQuery("Data").Order("Str").Limit(limit)
   347  		if cur.String() != "" {
   348  			q = q.Start(cur)
   349  		}
   350  		it := q.Run(ctx)
   351  
   352  		count := 0
   353  		for {
   354  			obj := &Data{}
   355  			_, err := it.Next(obj)
   356  			if err == datastore.Done {
   357  				break
   358  			} else if err != nil {
   359  				t.Fatal(err)
   360  			}
   361  
   362  			dataList = append(dataList, obj)
   363  			count++
   364  		}
   365  		if count != limit {
   366  			break
   367  		}
   368  
   369  		cur, err = it.Cursor()
   370  		if err != nil {
   371  			t.Fatal(err)
   372  		}
   373  		if cur.String() == "" {
   374  			break outer
   375  		}
   376  	}
   377  
   378  	if v := len(dataList); v != 100 {
   379  		t.Errorf("unexpected: %v", v)
   380  	}
   381  }
   382  
   383  func TestAEDatastore_ErrConcurrentTransaction(t *testing.T) {
   384  	ctx, close, err := newContext()
   385  	if err != nil {
   386  		t.Fatal(err)
   387  	}
   388  	defer close()
   389  
   390  	type Data struct {
   391  		Str string
   392  	}
   393  
   394  	key := datastore.NewKey(ctx, "Data", "a", 0, nil)
   395  	_, err = datastore.Put(ctx, key, &Data{})
   396  	if err != nil {
   397  		t.Fatal(err)
   398  	}
   399  
   400  	// ErrConcurrentTransaction will be occur
   401  	err = datastore.RunInTransaction(ctx, func(txCtx1 netcontext.Context) error {
   402  		err := datastore.Get(txCtx1, key, &Data{})
   403  		if err != nil {
   404  			return err
   405  		}
   406  
   407  		err = datastore.RunInTransaction(ctx, func(txCtx2 netcontext.Context) error {
   408  			err := datastore.Get(txCtx2, key, &Data{})
   409  			if err != nil {
   410  				return err
   411  			}
   412  
   413  			_, err = datastore.Put(txCtx2, key, &Data{Str: "#2"})
   414  			return err
   415  		}, &datastore.TransactionOptions{XG: true})
   416  		if err != nil {
   417  			return err
   418  		}
   419  
   420  		_, err = datastore.Put(txCtx1, key, &Data{Str: "#1"})
   421  		return err
   422  	}, &datastore.TransactionOptions{XG: true})
   423  	if err != datastore.ErrConcurrentTransaction {
   424  		t.Fatal(err)
   425  	}
   426  }
   427  
   428  func TestAEDatastore_ObjectHasObjectSlice(t *testing.T) {
   429  	type Inner struct {
   430  		A string
   431  		B string
   432  	}
   433  
   434  	type Data struct {
   435  		Slice []Inner
   436  	}
   437  
   438  	ps, err := datastore.SaveStruct(&Data{
   439  		Slice: []Inner{
   440  			{A: "A1", B: "B1"},
   441  			{A: "A2", B: "B2"},
   442  			{A: "A3", B: "B3"},
   443  		},
   444  	})
   445  	if err != nil {
   446  		t.Fatal(err)
   447  	}
   448  
   449  	if v := len(ps); v != 6 {
   450  		t.Fatalf("unexpected: %v", v)
   451  	}
   452  
   453  	sort.SliceStable(ps, func(i, j int) bool {
   454  		a := ps[i]
   455  		b := ps[j]
   456  		if v := strings.Compare(a.Name, b.Name); v < 0 {
   457  			return true
   458  		}
   459  		if v := strings.Compare(a.Value.(string), b.Value.(string)); v < 0 {
   460  			return true
   461  		}
   462  
   463  		return false
   464  	})
   465  
   466  	expects := []struct {
   467  		Name     string
   468  		Value    string
   469  		Multiple bool
   470  	}{
   471  		{"Slice.A", "A1", true},
   472  		{"Slice.A", "A2", true},
   473  		{"Slice.A", "A3", true},
   474  		{"Slice.B", "B1", true},
   475  		{"Slice.B", "B2", true},
   476  		{"Slice.B", "B3", true},
   477  	}
   478  	for idx, expect := range expects {
   479  		t.Logf("idx: %d", idx)
   480  		p := ps[idx]
   481  		if v := p.Name; v != expect.Name {
   482  			t.Errorf("unexpected: %v", v)
   483  		}
   484  		if v := p.Value.(string); v != expect.Value {
   485  			t.Errorf("unexpected: %v", v)
   486  		}
   487  		if v := p.Multiple; v != expect.Multiple {
   488  			t.Errorf("unexpected: %v", v)
   489  		}
   490  	}
   491  }
   492  
   493  func TestAEDatastore_GeoPoint(t *testing.T) {
   494  	ctx, close, err := newContext()
   495  	if err != nil {
   496  		t.Fatal(err)
   497  	}
   498  	defer close()
   499  
   500  	type Data struct {
   501  		A appengine.GeoPoint
   502  		// B *appengine.GeoPoint
   503  		C []appengine.GeoPoint
   504  		// D []*appengine.GeoPoint
   505  	}
   506  
   507  	obj := &Data{
   508  		A: appengine.GeoPoint{Lat: 1.1, Lng: 2.2},
   509  		// B: &appengine.GeoPoint{3.3, 4.4},
   510  		C: []appengine.GeoPoint{
   511  			{Lat: 5.5, Lng: 6.6},
   512  			{Lat: 7.7, Lng: 8.8},
   513  		},
   514  		/*
   515  			D: []*appengine.GeoPoint{
   516  				{9.9, 10.10},
   517  				{11.11, 12.12},
   518  			},
   519  		*/
   520  	}
   521  
   522  	key, err := datastore.Put(ctx, datastore.NewIncompleteKey(ctx, "Data", nil), obj)
   523  	if err != nil {
   524  		t.Fatal(err)
   525  	}
   526  
   527  	obj = &Data{}
   528  	err = datastore.Get(ctx, key, obj)
   529  	if err != nil {
   530  		t.Fatal(err)
   531  	}
   532  
   533  	if v := obj.A.Lat; v != 1.1 {
   534  		t.Errorf("unexpected: %v", v)
   535  	}
   536  	if v := obj.A.Lng; v != 2.2 {
   537  		t.Errorf("unexpected: %v", v)
   538  	}
   539  
   540  	if v := len(obj.C); v != 2 {
   541  		t.Fatalf("unexpected: %v", v)
   542  	}
   543  	if v := obj.C[0].Lat; v != 5.5 {
   544  		t.Errorf("unexpected: %v", v)
   545  	}
   546  	if v := obj.C[0].Lng; v != 6.6 {
   547  		t.Errorf("unexpected: %v", v)
   548  	}
   549  	if v := obj.C[1].Lat; v != 7.7 {
   550  		t.Errorf("unexpected: %v", v)
   551  	}
   552  	if v := obj.C[1].Lng; v != 8.8 {
   553  		t.Errorf("unexpected: %v", v)
   554  	}
   555  }
   556  
   557  func TestAEDatastore_PutInterface(t *testing.T) {
   558  	ctx, close, err := newContext()
   559  	if err != nil {
   560  		t.Fatal(err)
   561  	}
   562  	defer close()
   563  
   564  	var e EntityInterface = &PutInterfaceTest{}
   565  
   566  	key := datastore.NewIncompleteKey(ctx, "Test", nil)
   567  	_, err = datastore.Put(ctx, key, e)
   568  	if err != nil {
   569  		t.Fatal(err)
   570  	}
   571  }
   572  
   573  func TestAEDatastore_PutAndGetPropertyList(t *testing.T) {
   574  	ctx, close, err := newContext()
   575  	if err != nil {
   576  		t.Fatal(err)
   577  	}
   578  	defer close()
   579  
   580  	var ps datastore.PropertyList
   581  	ps = append(ps, datastore.Property{
   582  		Name:  "A",
   583  		Value: "A-Value",
   584  	})
   585  	ps = append(ps, datastore.Property{
   586  		Name:  "B",
   587  		Value: true,
   588  	})
   589  
   590  	key := datastore.NewIncompleteKey(ctx, "Test", nil)
   591  	// passed datastore.PropertyList, would be error.
   592  	_, err = datastore.Put(ctx, key, ps)
   593  	if err != datastore.ErrInvalidEntityType {
   594  		t.Fatal(err)
   595  	}
   596  
   597  	// ok!
   598  	key, err = datastore.Put(ctx, key, &ps)
   599  	if err != nil {
   600  		t.Fatal(err)
   601  	}
   602  
   603  	// passed datastore.PropertyList, would be error.
   604  	ps = datastore.PropertyList{}
   605  	err = datastore.Get(ctx, key, ps)
   606  	if err != datastore.ErrInvalidEntityType {
   607  		t.Fatal(err)
   608  	}
   609  
   610  	// ok!
   611  	ps = datastore.PropertyList{}
   612  	err = datastore.Get(ctx, key, &ps)
   613  	if err != nil {
   614  		t.Fatal(err)
   615  	}
   616  
   617  	if v := len(ps); v != 2 {
   618  		t.Fatalf("unexpected: %v", v)
   619  	}
   620  }
   621  
   622  func TestAEDatastore_PutAndGetMultiPropertyListSlice(t *testing.T) {
   623  	ctx, close, err := newContext()
   624  	if err != nil {
   625  		t.Fatal(err)
   626  	}
   627  	defer close()
   628  
   629  	var pss []datastore.PropertyList
   630  	var keys []*datastore.Key
   631  	{
   632  		var ps datastore.PropertyList
   633  		ps = append(ps, datastore.Property{
   634  			Name:  "A",
   635  			Value: "A-Value",
   636  		})
   637  		ps = append(ps, datastore.Property{
   638  			Name:  "B",
   639  			Value: true,
   640  		})
   641  
   642  		key := datastore.NewIncompleteKey(ctx, "Test", nil)
   643  
   644  		pss = append(pss, ps)
   645  		keys = append(keys, key)
   646  	}
   647  
   648  	// passed *[]datastore.PropertyList, would be error.
   649  	_, err = datastore.PutMulti(ctx, keys, &pss)
   650  	if err == nil {
   651  		t.Fatal(err)
   652  	}
   653  
   654  	// ok! []datastore.PropertyList
   655  	keys, err = datastore.PutMulti(ctx, keys, pss)
   656  	if err != nil {
   657  		t.Fatal(err)
   658  	}
   659  
   660  	// passed *[]datastore.PropertyList, would be error.
   661  	pss = []datastore.PropertyList{}
   662  	err = datastore.GetMulti(ctx, keys, &pss)
   663  	if err == nil {
   664  		t.Fatal(err)
   665  	}
   666  
   667  	// passed []datastore.PropertyList with length 0, would be error.
   668  	pss = make([]datastore.PropertyList, 0)
   669  	err = datastore.GetMulti(ctx, keys, pss)
   670  	if err == nil {
   671  		t.Fatal(err)
   672  	}
   673  
   674  	// ok! []datastore.PropertyList with length == len(keys)
   675  	pss = make([]datastore.PropertyList, len(keys))
   676  	err = datastore.GetMulti(ctx, keys, pss)
   677  	if err != nil {
   678  		t.Fatal(err)
   679  	}
   680  
   681  	if v := len(pss); v != 1 {
   682  		t.Fatalf("unexpected: %v", v)
   683  	}
   684  }
   685  
   686  func TestAEDatastore_PutAndGetBareStruct(t *testing.T) {
   687  	ctx, close, err := newContext()
   688  	if err != nil {
   689  		t.Fatal(err)
   690  	}
   691  	defer close()
   692  
   693  	type Data struct {
   694  		Name string
   695  	}
   696  
   697  	key := datastore.NewIncompleteKey(ctx, "Test", nil)
   698  	// passed Data, would be error.
   699  	_, err = datastore.Put(ctx, key, Data{Name: "A"})
   700  	if err != datastore.ErrInvalidEntityType {
   701  		t.Fatal(err)
   702  	}
   703  
   704  	// ok! *Data
   705  	key, err = datastore.Put(ctx, key, &Data{Name: "A"})
   706  	if err != nil {
   707  		t.Fatal(err)
   708  	}
   709  
   710  	// ok! but struct are copied. can't watching Get result.
   711  	obj := Data{}
   712  	err = datastore.Get(ctx, key, obj)
   713  	if err != datastore.ErrInvalidEntityType {
   714  		t.Fatal(err)
   715  	}
   716  
   717  	if v := obj.Name; v != "" {
   718  		t.Errorf("unexpected: '%v'", v)
   719  	}
   720  }
   721  
   722  func TestAEDatastore_PutAndGetMultiBareStruct(t *testing.T) {
   723  	ctx, close, err := newContext()
   724  	if err != nil {
   725  		t.Fatal(err)
   726  	}
   727  	defer close()
   728  
   729  	type Data struct {
   730  		Name string
   731  	}
   732  
   733  	var list []Data
   734  	var keys []*datastore.Key
   735  	{
   736  		obj := Data{Name: "A"}
   737  		key := datastore.NewIncompleteKey(ctx, "Test", nil)
   738  
   739  		list = append(list, obj)
   740  		keys = append(keys, key)
   741  	}
   742  
   743  	// ok!
   744  	keys, err = datastore.PutMulti(ctx, keys, list)
   745  	if err != nil {
   746  		t.Fatal(err)
   747  	}
   748  
   749  	// passed []Data with length 0, would be error.
   750  	list = make([]Data, 0)
   751  	err = datastore.GetMulti(ctx, keys, list)
   752  	if err == nil {
   753  		t.Fatal(err)
   754  	}
   755  
   756  	// ok! []Data with length == len(keys)
   757  	list = make([]Data, len(keys))
   758  	err = datastore.GetMulti(ctx, keys, list)
   759  	if err != nil {
   760  		t.Fatal(err)
   761  	}
   762  
   763  	if v := len(list); v != 1 {
   764  		t.Fatalf("unexpected: '%v'", v)
   765  	}
   766  	if v := list[0].Name; v != "A" {
   767  		t.Errorf("unexpected: '%v'", v)
   768  	}
   769  }
   770  
   771  func TestAEDatastore_PutAndGetStringSynonym(t *testing.T) {
   772  	ctx, close, err := newContext()
   773  	if err != nil {
   774  		t.Fatal(err)
   775  	}
   776  	defer close()
   777  
   778  	type Email string
   779  
   780  	type Data struct {
   781  		Email Email
   782  	}
   783  
   784  	key, err := datastore.Put(ctx, datastore.NewIncompleteKey(ctx, "Data", nil), &Data{Email: "test@example.com"})
   785  	if err != nil {
   786  		t.Fatal(err)
   787  	}
   788  
   789  	obj := &Data{}
   790  	err = datastore.Get(ctx, key, obj)
   791  	if err != nil {
   792  		t.Fatal(err)
   793  	}
   794  
   795  	if v := obj.Email; v != "test@example.com" {
   796  		t.Errorf("unexpected: '%v'", v)
   797  	}
   798  }
   799  
   800  func TestAEDatastore_QueryNextByPropertyList(t *testing.T) {
   801  	ctx, close, err := newContext()
   802  	if err != nil {
   803  		t.Fatal(err)
   804  	}
   805  	defer close()
   806  
   807  	type Data struct {
   808  		Name string
   809  	}
   810  
   811  	_, err = datastore.Put(ctx, datastore.NewIncompleteKey(ctx, "Data", nil), &Data{Name: "A"})
   812  	if err != nil {
   813  		t.Fatal(err)
   814  	}
   815  
   816  	q := datastore.NewQuery("Data")
   817  
   818  	{ // passed datastore.PropertyList, would be error.
   819  		iter := q.Run(ctx)
   820  
   821  		var ps datastore.PropertyList
   822  		_, err = iter.Next(ps)
   823  		if err == nil {
   824  			t.Fatal(err)
   825  		}
   826  	}
   827  	{ // ok! *datastore.PropertyList
   828  		iter := q.Run(ctx)
   829  
   830  		var ps datastore.PropertyList
   831  		_, err = iter.Next(&ps)
   832  		if err != nil {
   833  			t.Fatal(err)
   834  		}
   835  	}
   836  }
   837  
   838  func TestAEDatastore_GetAllByPropertyListSlice(t *testing.T) {
   839  	ctx, close, err := newContext()
   840  	if err != nil {
   841  		t.Fatal(err)
   842  	}
   843  	defer close()
   844  
   845  	type Data struct {
   846  		Name string
   847  	}
   848  
   849  	_, err = datastore.Put(ctx, datastore.NewIncompleteKey(ctx, "Data", nil), &Data{Name: "A"})
   850  	if err != nil {
   851  		t.Fatal(err)
   852  	}
   853  
   854  	q := datastore.NewQuery("Data")
   855  	var psList []datastore.PropertyList
   856  
   857  	// passed []datastore.PropertyList, would be error.
   858  	_, err = q.GetAll(ctx, psList)
   859  	if err == nil {
   860  		t.Fatal(err)
   861  	}
   862  
   863  	// ok! *[]datastore.PropertyList
   864  	psList = nil
   865  	_, err = q.GetAll(ctx, &psList)
   866  	if err != nil {
   867  		t.Fatal(err)
   868  	}
   869  }
   870  
   871  func TestAEDatastore_Namespace(t *testing.T) {
   872  	ctx, close, err := newContext()
   873  	if err != nil {
   874  		t.Fatal(err)
   875  	}
   876  	defer close()
   877  
   878  	type Data struct {
   879  		Name string
   880  	}
   881  
   882  	nsCtx, err := appengine.Namespace(ctx, "no1")
   883  	if err != nil {
   884  		t.Fatal(err)
   885  	}
   886  
   887  	key := datastore.NewKey(nsCtx, "Test", "", 1, nil)
   888  	if v := key.String(); v != "/Test,1" {
   889  		t.Fatalf("unexpected: %v", v)
   890  	}
   891  	vanillaKey := datastore.NewKey(ctx, "Test", "", 1, nil)
   892  	if v := vanillaKey.String(); v != "/Test,1" {
   893  		t.Fatalf("unexpected: %v", v)
   894  	}
   895  
   896  	_, err = datastore.Put(ctx, key, &Data{"Name #1"})
   897  	if err != nil {
   898  		t.Fatal(err)
   899  	}
   900  
   901  	err = datastore.Get(ctx, vanillaKey, &Data{})
   902  	if err != datastore.ErrNoSuchEntity {
   903  		t.Fatal(err)
   904  	}
   905  
   906  	err = datastore.Get(ctx, key, &Data{})
   907  	if err != nil {
   908  		t.Fatal(err)
   909  	}
   910  
   911  	q := datastore.NewQuery("Test")
   912  	q = q.KeysOnly()
   913  
   914  	var keys []*datastore.Key
   915  
   916  	keys, err = q.GetAll(ctx, nil)
   917  	if err != nil {
   918  		t.Fatal(err)
   919  	}
   920  	if v := len(keys); v != 0 {
   921  		t.Fatalf("unexpected: %v", v)
   922  	}
   923  
   924  	keys, err = q.GetAll(nsCtx, nil)
   925  	if err != nil {
   926  		t.Fatal(err)
   927  	}
   928  	if v := len(keys); v != 1 {
   929  		t.Fatalf("unexpected: %v", v)
   930  	}
   931  }
   932  
   933  func TestAEDatastore_KindlessQueryWithAncestor(t *testing.T) {
   934  	ctx, close, err := newContext()
   935  	if err != nil {
   936  		t.Fatal(err)
   937  	}
   938  	defer close()
   939  
   940  	type A struct {
   941  		A string
   942  	}
   943  	type B struct {
   944  		B int
   945  	}
   946  
   947  	ancestorKey := datastore.NewKey(ctx, "Ancestor", "foo", 0, nil)
   948  
   949  	_, err = datastore.Put(ctx, datastore.NewIncompleteKey(ctx, "A", ancestorKey), &A{A: "1"})
   950  	if err != nil {
   951  		t.Fatal(err)
   952  	}
   953  	_, err = datastore.Put(ctx, datastore.NewIncompleteKey(ctx, "A", ancestorKey), &A{A: "1"})
   954  	if err != nil {
   955  		t.Fatal(err)
   956  	}
   957  	_, err = datastore.Put(ctx, datastore.NewIncompleteKey(ctx, "B", ancestorKey), &B{B: 1})
   958  	if err != nil {
   959  		t.Fatal(err)
   960  	}
   961  	_, err = datastore.Put(ctx, datastore.NewIncompleteKey(ctx, "B", ancestorKey), &B{B: 1})
   962  	if err != nil {
   963  		t.Fatal(err)
   964  	}
   965  
   966  	var pss []datastore.PropertyList
   967  	keys, err := datastore.NewQuery("").Ancestor(ancestorKey).GetAll(ctx, &pss)
   968  	if err != nil {
   969  		t.Fatal(err)
   970  	}
   971  
   972  	if v := len(keys); v != 4 {
   973  		t.Fatalf("unexpected: %v", v)
   974  	}
   975  	if v := len(pss); v != 4 {
   976  		t.Fatalf("unexpected: %v", v)
   977  	}
   978  }