go.mercari.io/datastore@v1.8.2/dsmiddleware/dslog/dslog_test.go (about)

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