go.mercari.io/datastore@v1.8.2/dsmiddleware/fishbone/fishbone_test.go (about)

     1  package fishbone
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"strings"
     7  	"testing"
     8  
     9  	"github.com/MakeNowJust/heredoc/v2"
    10  	"go.mercari.io/datastore"
    11  	"go.mercari.io/datastore/dsmiddleware/dslog"
    12  	"go.mercari.io/datastore/internal/testutils"
    13  	"google.golang.org/api/iterator"
    14  )
    15  
    16  func TestFishBone_QueryWithoutTx(t *testing.T) {
    17  	ctx, client, cleanUp := testutils.SetupCloudDatastore(t)
    18  	defer cleanUp()
    19  
    20  	var logs []string
    21  	logf := func(ctx context.Context, format string, args ...interface{}) {
    22  		t.Logf(format, args...)
    23  		logs = append(logs, fmt.Sprintf(format, args...))
    24  	}
    25  
    26  	// setup. strategies are first in - first apply.
    27  
    28  	bLog := dslog.NewLogger("before: ", logf)
    29  	client.AppendMiddleware(bLog)
    30  	defer func() {
    31  		// stop logging before cleanUp func called.
    32  		client.RemoveMiddleware(bLog)
    33  	}()
    34  
    35  	m := New()
    36  	client.AppendMiddleware(m)
    37  	defer func() {
    38  		// stop logging before cleanUp func called.
    39  		client.RemoveMiddleware(m)
    40  	}()
    41  
    42  	aLog := dslog.NewLogger("after: ", logf)
    43  	client.AppendMiddleware(aLog)
    44  	defer func() {
    45  		// stop logging before cleanUp func called.
    46  		client.RemoveMiddleware(aLog)
    47  	}()
    48  
    49  	// exec.
    50  
    51  	type Data struct {
    52  		Name string
    53  	}
    54  
    55  	const size = 3
    56  
    57  	keys := make([]datastore.Key, size)
    58  	list := make([]*Data, size)
    59  	for i := 0; i < size; i++ {
    60  		keys[i] = client.NameKey("Data", fmt.Sprintf("#%d", i+1), nil)
    61  		list[i] = &Data{
    62  			Name: fmt.Sprintf("#%d", i+1),
    63  		}
    64  	}
    65  	_, err := client.PutMulti(ctx, keys, list)
    66  	if err != nil {
    67  		t.Fatal(err)
    68  	}
    69  
    70  	q := client.NewQuery("Data").Order("-Name")
    71  
    72  	// Run
    73  	iter := client.Run(ctx, q)
    74  
    75  	// Next
    76  	cnt := 0
    77  	for {
    78  		obj := &Data{}
    79  		key, err := iter.Next(obj)
    80  		if err == iterator.Done {
    81  			break
    82  		} else if err != nil {
    83  			t.Fatal(err)
    84  		}
    85  		if v := obj.Name; v == "" || v != key.Name() {
    86  			t.Errorf("unexpected: %v", cnt)
    87  		}
    88  		cnt++
    89  	}
    90  	if cnt != size {
    91  		t.Errorf("unexpected: %v", cnt)
    92  	}
    93  
    94  	// GetAll
    95  	q = client.NewQuery("Data").Order("-Name")
    96  	list = nil
    97  	keys, err = client.GetAll(ctx, q, &list)
    98  	if err != nil {
    99  		t.Fatal(err)
   100  	}
   101  	if v := len(list); v != size {
   102  		t.Errorf("unexpected: %v", v)
   103  	}
   104  	for idx, obj := range list {
   105  		if v := obj.Name; v == "" || v != keys[idx].Name() {
   106  			t.Errorf("unexpected: %v", v)
   107  		}
   108  	}
   109  
   110  	expected := heredoc.Doc(`
   111  		before: PutMultiWithoutTx #1, len(keys)=3, keys=[/Data,#1, /Data,#2, /Data,#3]
   112  		after: PutMultiWithoutTx #1, len(keys)=3, keys=[/Data,#1, /Data,#2, /Data,#3]
   113  		after: PutMultiWithoutTx #1, keys=[/Data,#1, /Data,#2, /Data,#3]
   114  		before: PutMultiWithoutTx #1, keys=[/Data,#1, /Data,#2, /Data,#3]
   115  		before: Run #2, q=v1:Data&or=-Name
   116  		after: Run #2, q=v1:Data&or=-Name&k=t
   117  		before: Next #3, q=v1:Data&or=-Name
   118  		after: Next #3, q=v1:Data&or=-Name
   119  		after: Next #3, key=/Data,#3
   120  		before: GetMultiWithoutTx #4, len(keys)=1, keys=[/Data,#3]
   121  		after: GetMultiWithoutTx #4, len(keys)=1, keys=[/Data,#3]
   122  		before: Next #3, key=/Data,#3
   123  		before: Next #5, q=v1:Data&or=-Name
   124  		after: Next #5, q=v1:Data&or=-Name
   125  		after: Next #5, key=/Data,#2
   126  		before: GetMultiWithoutTx #6, len(keys)=1, keys=[/Data,#2]
   127  		after: GetMultiWithoutTx #6, len(keys)=1, keys=[/Data,#2]
   128  		before: Next #5, key=/Data,#2
   129  		before: Next #7, q=v1:Data&or=-Name
   130  		after: Next #7, q=v1:Data&or=-Name
   131  		after: Next #7, key=/Data,#1
   132  		before: GetMultiWithoutTx #8, len(keys)=1, keys=[/Data,#1]
   133  		after: GetMultiWithoutTx #8, len(keys)=1, keys=[/Data,#1]
   134  		before: Next #7, key=/Data,#1
   135  		before: Next #9, q=v1:Data&or=-Name
   136  		after: Next #9, q=v1:Data&or=-Name
   137  		after: Next #9, err=no more items in iterator
   138  		before: Next #9, err=no more items in iterator
   139  		before: GetAll #10, q=v1:Data&or=-Name
   140  		after: GetAll #10, q=v1:Data&or=-Name&k=t
   141  		after: GetAll #10, len(keys)=3, keys=[/Data,#3, /Data,#2, /Data,#1]
   142  		before: GetMultiWithoutTx #11, len(keys)=3, keys=[/Data,#3, /Data,#2, /Data,#1]
   143  		after: GetMultiWithoutTx #11, len(keys)=3, keys=[/Data,#3, /Data,#2, /Data,#1]
   144  		before: GetAll #10, len(keys)=3, keys=[/Data,#3, /Data,#2, /Data,#1]
   145  	`)
   146  
   147  	if v := strings.Join(logs, "\n") + "\n"; v != expected {
   148  		t.Errorf("unexpected: %v", v)
   149  	}
   150  }
   151  
   152  func TestFishBone_QueryWithTx(t *testing.T) {
   153  	ctx, client, cleanUp := testutils.SetupCloudDatastore(t)
   154  	defer cleanUp()
   155  
   156  	var logs []string
   157  	logf := func(ctx context.Context, format string, args ...interface{}) {
   158  		t.Logf(format, args...)
   159  		logs = append(logs, fmt.Sprintf(format, args...))
   160  	}
   161  
   162  	// setup. strategies are first in - first apply.
   163  
   164  	bLog := dslog.NewLogger("before: ", logf)
   165  	client.AppendMiddleware(bLog)
   166  	defer func() {
   167  		// stop logging before cleanUp func called.
   168  		client.RemoveMiddleware(bLog)
   169  	}()
   170  
   171  	m := New()
   172  	client.AppendMiddleware(m)
   173  	defer func() {
   174  		// stop logging before cleanUp func called.
   175  		client.RemoveMiddleware(m)
   176  	}()
   177  
   178  	aLog := dslog.NewLogger("after: ", logf)
   179  	client.AppendMiddleware(aLog)
   180  	defer func() {
   181  		// stop logging before cleanUp func called.
   182  		client.RemoveMiddleware(aLog)
   183  	}()
   184  
   185  	// exec.
   186  
   187  	type Data struct {
   188  		Name string
   189  	}
   190  
   191  	const size = 3
   192  
   193  	parentKey := client.NameKey("Parent", "p", nil)
   194  	keys := make([]datastore.Key, size)
   195  	list := make([]*Data, size)
   196  	for i := 0; i < size; i++ {
   197  		keys[i] = client.NameKey("Data", fmt.Sprintf("#%d", i+1), parentKey)
   198  		list[i] = &Data{
   199  			Name: fmt.Sprintf("#%d", i+1),
   200  		}
   201  	}
   202  	_, err := client.PutMulti(ctx, keys, list)
   203  	if err != nil {
   204  		t.Fatal(err)
   205  	}
   206  
   207  	tx, err := client.NewTransaction(ctx)
   208  	if err != nil {
   209  		t.Fatal(err)
   210  	}
   211  	defer func() {
   212  		err := tx.Rollback()
   213  		if err != nil {
   214  			t.Fatal(err)
   215  		}
   216  	}()
   217  
   218  	q := client.NewQuery("Data").Order("-Name").Ancestor(parentKey).Transaction(tx)
   219  
   220  	// Run
   221  	iter := client.Run(ctx, q)
   222  
   223  	// Next
   224  	cnt := 0
   225  	for {
   226  		obj := &Data{}
   227  		key, err := iter.Next(obj)
   228  		if err == iterator.Done {
   229  			break
   230  		} else if err != nil {
   231  			t.Fatal(err)
   232  		}
   233  		if v := obj.Name; v == "" || v != key.Name() {
   234  			t.Errorf("unexpected: %v", cnt)
   235  		}
   236  		cnt++
   237  	}
   238  	if cnt != size {
   239  		t.Errorf("unexpected: %v", cnt)
   240  	}
   241  
   242  	// GetAll
   243  	q = client.NewQuery("Data").Order("-Name").Ancestor(parentKey).Transaction(tx)
   244  	list = nil
   245  	keys, err = client.GetAll(ctx, q, &list)
   246  	if err != nil {
   247  		t.Fatal(err)
   248  	}
   249  	if v := len(list); v != size {
   250  		t.Errorf("unexpected: %v", v)
   251  	}
   252  	for idx, obj := range list {
   253  		if v := obj.Name; v == "" || v != keys[idx].Name() {
   254  			t.Errorf("unexpected: %v", v)
   255  		}
   256  	}
   257  
   258  	expected := heredoc.Doc(`
   259  		before: PutMultiWithoutTx #1, len(keys)=3, keys=[/Parent,p/Data,#1, /Parent,p/Data,#2, /Parent,p/Data,#3]
   260  		after: PutMultiWithoutTx #1, len(keys)=3, keys=[/Parent,p/Data,#1, /Parent,p/Data,#2, /Parent,p/Data,#3]
   261  		after: PutMultiWithoutTx #1, keys=[/Parent,p/Data,#1, /Parent,p/Data,#2, /Parent,p/Data,#3]
   262  		before: PutMultiWithoutTx #1, keys=[/Parent,p/Data,#1, /Parent,p/Data,#2, /Parent,p/Data,#3]
   263  		before: Run #2, q=v1:Data&a=/Parent,p&t=t&or=-Name
   264  		after: Run #2, q=v1:Data&a=/Parent,p&t=t&or=-Name&k=t
   265  		before: Next #3, q=v1:Data&a=/Parent,p&t=t&or=-Name
   266  		after: Next #3, q=v1:Data&a=/Parent,p&t=t&or=-Name
   267  		after: Next #3, key=/Parent,p/Data,#3
   268  		before: GetMultiWithTx #4, len(keys)=1, keys=[/Parent,p/Data,#3]
   269  		after: GetMultiWithTx #4, len(keys)=1, keys=[/Parent,p/Data,#3]
   270  		before: Next #3, key=/Parent,p/Data,#3
   271  		before: Next #5, q=v1:Data&a=/Parent,p&t=t&or=-Name
   272  		after: Next #5, q=v1:Data&a=/Parent,p&t=t&or=-Name
   273  		after: Next #5, key=/Parent,p/Data,#2
   274  		before: GetMultiWithTx #6, len(keys)=1, keys=[/Parent,p/Data,#2]
   275  		after: GetMultiWithTx #6, len(keys)=1, keys=[/Parent,p/Data,#2]
   276  		before: Next #5, key=/Parent,p/Data,#2
   277  		before: Next #7, q=v1:Data&a=/Parent,p&t=t&or=-Name
   278  		after: Next #7, q=v1:Data&a=/Parent,p&t=t&or=-Name
   279  		after: Next #7, key=/Parent,p/Data,#1
   280  		before: GetMultiWithTx #8, len(keys)=1, keys=[/Parent,p/Data,#1]
   281  		after: GetMultiWithTx #8, len(keys)=1, keys=[/Parent,p/Data,#1]
   282  		before: Next #7, key=/Parent,p/Data,#1
   283  		before: Next #9, q=v1:Data&a=/Parent,p&t=t&or=-Name
   284  		after: Next #9, q=v1:Data&a=/Parent,p&t=t&or=-Name
   285  		after: Next #9, err=no more items in iterator
   286  		before: Next #9, err=no more items in iterator
   287  		before: GetAll #10, q=v1:Data&a=/Parent,p&t=t&or=-Name
   288  		after: GetAll #10, q=v1:Data&a=/Parent,p&t=t&or=-Name&k=t
   289  		after: GetAll #10, len(keys)=3, keys=[/Parent,p/Data,#3, /Parent,p/Data,#2, /Parent,p/Data,#1]
   290  		before: GetMultiWithTx #11, len(keys)=3, keys=[/Parent,p/Data,#3, /Parent,p/Data,#2, /Parent,p/Data,#1]
   291  		after: GetMultiWithTx #11, len(keys)=3, keys=[/Parent,p/Data,#3, /Parent,p/Data,#2, /Parent,p/Data,#1]
   292  		before: GetAll #10, len(keys)=3, keys=[/Parent,p/Data,#3, /Parent,p/Data,#2, /Parent,p/Data,#1]
   293  	`)
   294  
   295  	if v := strings.Join(logs, "\n") + "\n"; v != expected {
   296  		t.Errorf("unexpected: %v", v)
   297  	}
   298  }