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

     1  package clouddatastore
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"math/rand"
     7  	"net"
     8  	"os"
     9  	"testing"
    10  	"time"
    11  
    12  	"go.mercari.io/datastore/testsuite"
    13  	_ "go.mercari.io/datastore/testsuite/dsmiddleware/dslog"
    14  	_ "go.mercari.io/datastore/testsuite/dsmiddleware/fishbone"
    15  	_ "go.mercari.io/datastore/testsuite/dsmiddleware/localcache"
    16  	_ "go.mercari.io/datastore/testsuite/dsmiddleware/rpcretry"
    17  	_ "go.mercari.io/datastore/testsuite/favcliptools"
    18  	_ "go.mercari.io/datastore/testsuite/realworld/recursivebatch"
    19  	_ "go.mercari.io/datastore/testsuite/realworld/tbf"
    20  
    21  	"github.com/bradfitz/gomemcache/memcache"
    22  	"github.com/gomodule/redigo/redis"
    23  	"go.mercari.io/datastore/dsmiddleware/chaosrpc"
    24  	"go.mercari.io/datastore/dsmiddleware/dsmemcache"
    25  	"go.mercari.io/datastore/dsmiddleware/localcache"
    26  	"go.mercari.io/datastore/dsmiddleware/rediscache"
    27  	"go.mercari.io/datastore/dsmiddleware/rpcretry"
    28  	"go.mercari.io/datastore/dsmiddleware/splitop"
    29  	"google.golang.org/api/iterator"
    30  )
    31  
    32  func cleanUp() error {
    33  	ctx := context.Background()
    34  	client, err := FromContext(ctx)
    35  	if err != nil {
    36  		return err
    37  	}
    38  	defer client.Close()
    39  
    40  	q := client.NewQuery("__kind__").KeysOnly()
    41  	iter := client.Run(ctx, q)
    42  	var kinds []string
    43  	for {
    44  		key, err := iter.Next(nil)
    45  		if err == iterator.Done {
    46  			break
    47  		}
    48  		if err != nil {
    49  			return err
    50  		}
    51  		kinds = append(kinds, key.Name())
    52  	}
    53  
    54  	for _, kind := range kinds {
    55  		q := client.NewQuery(kind).KeysOnly()
    56  		keys, err := client.GetAll(ctx, q, nil)
    57  		if err != nil {
    58  			return err
    59  		}
    60  		err = client.DeleteMulti(ctx, keys)
    61  		if err != nil {
    62  			return err
    63  		}
    64  	}
    65  
    66  	return nil
    67  }
    68  
    69  func TestCloudDatastoreTestSuite(t *testing.T) {
    70  	ctx := context.Background()
    71  	for name, test := range testsuite.TestSuite {
    72  		t.Run(name, func(t *testing.T) {
    73  			defer cleanUp()
    74  
    75  			datastore, err := FromContext(ctx)
    76  			if err != nil {
    77  				t.Fatal(err)
    78  			}
    79  			ctx = testsuite.WrapCloudFlag(ctx)
    80  			test(ctx, t, datastore)
    81  		})
    82  	}
    83  }
    84  
    85  func TestCloudDatastoreWithLocalCacheTestSuite(t *testing.T) {
    86  	ctx := context.Background()
    87  	for name, test := range testsuite.TestSuite {
    88  		t.Run(name, func(t *testing.T) {
    89  			switch name {
    90  			// Skip the failure that happens when you firstly appended another middleware layer.
    91  			case
    92  				"LocalCache_Basic",
    93  				"LocalCache_WithIncludeKinds",
    94  				"LocalCache_WithExcludeKinds",
    95  				"LocalCache_WithKeyFilter",
    96  				"FishBone_QueryWithoutTx":
    97  				t.SkipNow()
    98  			// It's annoying to avoid failure test. I think there is no problem in practical use. I believe...
    99  			case "PutAndGet_TimeTime":
   100  				t.SkipNow()
   101  			}
   102  
   103  			defer cleanUp()
   104  
   105  			datastore, err := FromContext(ctx)
   106  			if err != nil {
   107  				t.Fatal(err)
   108  			}
   109  
   110  			ch := localcache.New()
   111  			datastore.AppendMiddleware(ch)
   112  
   113  			ctx = testsuite.WrapCloudFlag(ctx)
   114  			test(ctx, t, datastore)
   115  		})
   116  	}
   117  }
   118  
   119  func TestCloudDatastoreWithRedisCacheTestSuite(t *testing.T) {
   120  	ctx := context.Background()
   121  	for name, test := range testsuite.TestSuite {
   122  		t.Run(name, func(t *testing.T) {
   123  			switch name {
   124  			// Skip the failure that happens when you firstly appended another middleware layer.
   125  			case
   126  				"LocalCache_Basic",
   127  				"LocalCache_WithIncludeKinds",
   128  				"LocalCache_WithExcludeKinds",
   129  				"LocalCache_WithKeyFilter",
   130  				"FishBone_QueryWithoutTx":
   131  				t.SkipNow()
   132  			// It's annoying to avoid failure test. I think there is no problem in practical use. I believe...
   133  			case "PutAndGet_TimeTime":
   134  				t.SkipNow()
   135  			}
   136  
   137  			defer cleanUp()
   138  
   139  			datastore, err := FromContext(ctx)
   140  			if err != nil {
   141  				t.Fatal(err)
   142  			}
   143  
   144  			dial, err := net.Dial("tcp", os.Getenv("REDIS_HOST")+":"+os.Getenv("REDIS_PORT"))
   145  			if err != nil {
   146  				t.Fatal(err)
   147  			}
   148  			defer dial.Close()
   149  			conn := redis.NewConn(dial, 100*time.Millisecond, 100*time.Millisecond)
   150  			defer conn.Close()
   151  
   152  			rc := rediscache.New(conn)
   153  			datastore.AppendMiddleware(rc)
   154  
   155  			ctx = testsuite.WrapCloudFlag(ctx)
   156  			test(ctx, t, datastore)
   157  		})
   158  	}
   159  }
   160  
   161  func TestCloudDatastoreWithMemcacheTestSuite(t *testing.T) {
   162  	ctx := context.Background()
   163  	for name, test := range testsuite.TestSuite {
   164  		t.Run(name, func(t *testing.T) {
   165  			switch name {
   166  			// Skip the failure that happens when you firstly appended another middleware layer.
   167  			case
   168  				"LocalCache_Basic",
   169  				"LocalCache_WithIncludeKinds",
   170  				"LocalCache_WithExcludeKinds",
   171  				"LocalCache_WithKeyFilter",
   172  				"FishBone_QueryWithoutTx":
   173  				t.SkipNow()
   174  			// It's annoying to avoid failure test. I think there is no problem in practical use. I believe...
   175  			case "PutAndGet_TimeTime":
   176  				t.SkipNow()
   177  			}
   178  
   179  			defer cleanUp()
   180  
   181  			datastore, err := FromContext(ctx)
   182  			if err != nil {
   183  				t.Fatal(err)
   184  			}
   185  
   186  			memcacheClient := memcache.New(os.Getenv("MEMCACHE_ADDR"))
   187  			ch := dsmemcache.New(
   188  				memcacheClient,
   189  			)
   190  			datastore.AppendMiddleware(ch)
   191  
   192  			ctx = testsuite.WrapCloudFlag(ctx)
   193  			test(ctx, t, datastore)
   194  		})
   195  	}
   196  }
   197  
   198  func TestCloudDatastoreWithSplitCallTestSuite(t *testing.T) {
   199  	ctx := context.Background()
   200  
   201  	thresholds := []int{0, 1, 2, 1000}
   202  	for _, threshold := range thresholds {
   203  		threshold := threshold
   204  		t.Run(fmt.Sprintf("threshold %d", threshold), func(t *testing.T) {
   205  			for name, test := range testsuite.TestSuite {
   206  				t.Run(name, func(t *testing.T) {
   207  					// Skip the failure that happens when you firstly appended another middleware layer.
   208  					switch name {
   209  					case
   210  						//"LocalCache_Basic",
   211  						"LocalCache_WithIncludeKinds",
   212  						"LocalCache_WithExcludeKinds",
   213  						"LocalCache_WithKeyFilter",
   214  						"FishBone_QueryWithoutTx":
   215  						t.SkipNow()
   216  					}
   217  
   218  					defer cleanUp()
   219  
   220  					datastore, err := FromContext(ctx)
   221  					if err != nil {
   222  						t.Fatal(err)
   223  					}
   224  
   225  					sc := splitop.New(
   226  						splitop.WithGetSplitThreshold(threshold),
   227  						splitop.WithLogger(func(ctx context.Context, format string, args ...interface{}) {
   228  							t.Logf(format, args...)
   229  						}),
   230  					)
   231  					datastore.AppendMiddleware(sc)
   232  
   233  					ctx = testsuite.WrapCloudFlag(ctx)
   234  					test(ctx, t, datastore)
   235  				})
   236  			}
   237  		})
   238  	}
   239  }
   240  
   241  func TestCloudDatastoreWithRPCRetryAndChaosRPCTestSuite(t *testing.T) {
   242  	ctx := context.Background()
   243  	for name, test := range testsuite.TestSuite {
   244  		t.Run(name, func(t *testing.T) {
   245  			// Skip the flaky tests.
   246  			switch name {
   247  			case
   248  				"Filter_PropertyTranslaterMustError":
   249  				t.SkipNow()
   250  			}
   251  
   252  			defer cleanUp()
   253  
   254  			datastore, err := FromContext(ctx)
   255  			if err != nil {
   256  				t.Fatal(err)
   257  			}
   258  
   259  			rr := rpcretry.New(
   260  				rpcretry.WithRetryLimit(10),
   261  				rpcretry.WithMinBackoffDuration(1),
   262  				rpcretry.WithMaxBackoffDuration(1),
   263  				rpcretry.WithLogger(func(ctx context.Context, format string, args ...interface{}) {
   264  					t.Logf(format, args...)
   265  				}),
   266  			)
   267  			datastore.AppendMiddleware(rr)
   268  
   269  			seed := time.Now().UnixNano()
   270  			t.Logf("chaos seed: %d", seed)
   271  			cr := chaosrpc.New(rand.NewSource(seed))
   272  			datastore.AppendMiddleware(cr)
   273  
   274  			ctx = testsuite.WrapCloudFlag(ctx)
   275  			test(ctx, t, datastore)
   276  		})
   277  	}
   278  }