...

Source file src/golang.conradwood.net/tests/ctx/server.go

Documentation: golang.conradwood.net/tests/ctx

     1  package main
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	apb "golang.conradwood.net/apis/auth"
     7  	"golang.conradwood.net/apis/common"
     8  	ge "golang.conradwood.net/apis/getestservice"
     9  	"golang.conradwood.net/go-easyops/auth"
    10  	"golang.conradwood.net/go-easyops/authremote"
    11  	"golang.conradwood.net/go-easyops/cmdline"
    12  	gcm "golang.conradwood.net/go-easyops/common"
    13  	pctx "golang.conradwood.net/go-easyops/ctx"
    14  	//"golang.conradwood.net/go-easyops/errors"
    15  	"flag"
    16  	"golang.conradwood.net/go-easyops/server"
    17  	"golang.conradwood.net/go-easyops/utils"
    18  	"google.golang.org/grpc"
    19  	"io"
    20  	"os"
    21  	"sync"
    22  	"time"
    23  )
    24  
    25  var (
    26  	run_sleep_tests = flag.Bool("run_sleep_tests", true, "extra tests to test if timeouts and cancels propagate accurately, they take a while...")
    27  	runlock         sync.Mutex
    28  	didrun          = false
    29  )
    30  
    31  func start_server() {
    32  	sd := server.NewServerDef()
    33  	sd.SetPort(3005)
    34  	sd.SetOnStartupCallback(run_tests)
    35  	sd.SetRegister(server.Register(
    36  		func(g *grpc.Server) error {
    37  			ge.RegisterCtxTestServer(g, &geServer{})
    38  			return nil
    39  		},
    40  	))
    41  	err := server.ServerStartup(sd)
    42  	utils.Bail("Unable to start server", err)
    43  }
    44  
    45  type geServer struct{}
    46  
    47  func (g *geServer) Sleep(ctx context.Context, req *ge.SleepRequest) (*common.Void, error) {
    48  	t := time.Duration(req.Seconds) * time.Second
    49  	fmt.Printf("Sleeping for %0.2f seconds\n", t.Seconds())
    50  	time.Sleep(t)
    51  	if ctx.Err() != nil {
    52  		return nil, ctx.Err()
    53  	}
    54  	return &common.Void{}, nil
    55  }
    56  
    57  func (g *geServer) TestFork(ctx context.Context, req *ge.RequiredContext) (*common.Void, error) {
    58  	err := AssertRequiredContext(ctx, req)
    59  	if err != nil {
    60  		return nil, err
    61  	}
    62  
    63  	nctx, err := auth.ForkContext(ctx)
    64  	if err != nil {
    65  		return nil, err
    66  	}
    67  	err = AssertEqualContexts(ctx, nctx)
    68  	if err != nil {
    69  		return nil, err
    70  	}
    71  
    72  	return &common.Void{}, nil
    73  }
    74  func (g *geServer) TestUnary(ctx context.Context, req *ge.RequiredContext) (*common.Void, error) {
    75  	err := AssertRequiredContext(ctx, req)
    76  	if err != nil {
    77  		return nil, err
    78  	}
    79  	return &common.Void{}, nil
    80  
    81  }
    82  func (g *geServer) TestStream(req *ge.RequiredContext, srv ge.CtxTest_TestStreamServer) error {
    83  	ctx := srv.Context()
    84  	err := AssertRequiredContext(ctx, req)
    85  	if err != nil {
    86  		return err
    87  	}
    88  
    89  	_, err = g.TestDeSer(ctx, req)
    90  	return err
    91  }
    92  func (g *geServer) TestDeSer(ctx context.Context, req *ge.RequiredContext) (*ge.SerialisedContext, error) {
    93  	err := AssertRequiredContext(ctx, req)
    94  	if err != nil {
    95  		return nil, err
    96  	}
    97  	fmt.Printf("TestDeSer: required (and received) context calling service: %s\n", auth.UserIDString(auth.GetService(ctx)))
    98  	m := map[string]string{"foo": "bar"}
    99  	ictx := authremote.DerivedContextWithRouting(ctx, m, true)
   100  	err = AssertRequiredContext(ictx, req)
   101  	if err != nil {
   102  		return nil, fmt.Errorf("broken derived context (%s)", err)
   103  	}
   104  
   105  	err = AssertEqualContexts(ctx, ictx)
   106  	if err != nil {
   107  		return nil, err
   108  	}
   109  
   110  	//	fmt.Printf("b\n")
   111  	b, err := auth.SerialiseContext(ctx)
   112  	if err != nil {
   113  		return nil, err
   114  	}
   115  
   116  	s, err := auth.SerialiseContextToString(ctx)
   117  	if err != nil {
   118  		return nil, err
   119  	}
   120  
   121  	ictx, err = auth.RecreateContextWithTimeout(time.Duration(10)*time.Second, b)
   122  	if err != nil {
   123  		return nil, err
   124  	}
   125  	err = AssertRequiredContext(ictx, req)
   126  	if err != nil {
   127  		return nil, err
   128  	}
   129  
   130  	err = AssertEqualContexts(ctx, ictx)
   131  	if err != nil {
   132  		return nil, err
   133  	}
   134  
   135  	sctx, err := auth.RecreateContextWithTimeout(time.Duration(10)*time.Second, []byte(s))
   136  	if err != nil {
   137  		return nil, err
   138  	}
   139  	err = AssertRequiredContext(sctx, req)
   140  	if err != nil {
   141  		return nil, err
   142  	}
   143  
   144  	err = AssertEqualContexts(ctx, sctx)
   145  	if err != nil {
   146  		return nil, err
   147  	}
   148  
   149  	if cmdline.ContextWithBuilder() {
   150  		ictx, err = pctx.DeserialiseContextFromString(s)
   151  		if err != nil {
   152  			return nil, err
   153  		}
   154  
   155  		err = AssertEqualContexts(ctx, ictx)
   156  		if err != nil {
   157  			return nil, err
   158  		}
   159  
   160  		if !pctx.IsSerialisedByBuilder(b) {
   161  			return nil, fmt.Errorf("ctx does not recognise its own (byte) serialised context")
   162  		}
   163  		if !pctx.IsSerialisedByBuilder([]byte(s)) {
   164  			return nil, fmt.Errorf("ctx does not recognise its own (byte) serialised context")
   165  		}
   166  		_, err = pctx.DeserialiseContext(b)
   167  		if err != nil {
   168  			return nil, err
   169  		}
   170  	}
   171  
   172  	res := &ge.SerialisedContext{
   173  		Data:    b,
   174  		SData:   s,
   175  		User:    auth.GetSignedUser(ctx),
   176  		Service: auth.GetSignedService(ctx),
   177  	}
   178  	return res, nil
   179  }
   180  func run_tests() {
   181  	runlock.Lock()
   182  	if didrun == true {
   183  		runlock.Unlock()
   184  		return
   185  	}
   186  	didrun = true
   187  	runlock.Unlock()
   188  	// first run a couple of very quick tests..
   189  	svc := authremote.GetLocalServiceAccount()
   190  	ctx := authremote.Context()
   191  	if ctx == nil {
   192  		panic("no context")
   193  	}
   194  	if svc != nil && auth.GetSignedService(ctx) == nil {
   195  		panic("missing service")
   196  	}
   197  	ctx = authremote.DerivedContextWithRouting(ctx, make(map[string]string), true)
   198  	if ctx == nil {
   199  		panic("no context")
   200  	}
   201  	if svc != nil && auth.GetSignedService(ctx) == nil {
   202  		panic("missing service")
   203  	}
   204  
   205  	cmdline.SetDatacenter(false)
   206  	run_all_tests()
   207  	cmdline.SetDatacenter(true)
   208  	run_all_tests()
   209  	if *run_sleep_tests {
   210  		sleepTests()
   211  	}
   212  	fmt.Printf("Done\n")
   213  	PrintResult()
   214  	os.Exit(0)
   215  
   216  }
   217  func run_all_tests() {
   218  	fmt.Printf("Running tests...\n")
   219  
   220  	cmdline.SetContextBuilderVersion(OLD_CONTEXT_VERSION)
   221  	t := NewTest("simple unary test")
   222  	ctx := authremote.Context()
   223  	_, err := ge.GetCtxTestClient().TestUnary(ctx, CreateContextObject(ctx))
   224  	t.Error(err)
   225  	t.Done()
   226  
   227  	cmdline.SetContextBuilderVersion(NEW_CONTEXT_VERSION)
   228  	t = NewTest("simple unary test")
   229  	ctx = authremote.Context()
   230  	_, err = ge.GetCtxTestClient().TestUnary(ctx, CreateContextObject(ctx))
   231  	t.Error(err)
   232  	t.Done()
   233  
   234  	cmdline.SetContextBuilderVersion(OLD_CONTEXT_VERSION)
   235  	t = NewTest("stream test")
   236  	ctx = authremote.Context()
   237  	srv, err := ge.GetCtxTestClient().TestStream(ctx, CreateContextObject(ctx))
   238  	t.Error(err)
   239  	t.Error(checkSrv(srv))
   240  	t.Done()
   241  
   242  	cmdline.SetContextBuilderVersion(NEW_CONTEXT_VERSION)
   243  	t = NewTest("stream test")
   244  	ctx = authremote.Context()
   245  	srv, err = ge.GetCtxTestClient().TestStream(ctx, CreateContextObject(ctx))
   246  	t.Error(err)
   247  	t.Error(checkSrv(srv))
   248  	t.Done()
   249  
   250  	checkStream("CallUnaryFromStream", func(ctx context.Context) (recv, error) {
   251  		return ge.GetCtxTestClient().CallUnaryFromStream(ctx, CreateContextObject(ctx))
   252  	})
   253  
   254  	checkStream("CallStreamFromStream", func(ctx context.Context) (recv, error) {
   255  		return ge.GetCtxTestClient().CallStreamFromStream(ctx, CreateContextObject(ctx))
   256  	})
   257  	checkUnary("CallStreamFromUnary", func(ctx context.Context) error {
   258  		_, err := ge.GetCtxTestClient().CallStreamFromUnary(ctx, CreateContextObject(ctx))
   259  		return err
   260  	})
   261  	checkUnary("CallUnaryFromUnary", func(ctx context.Context) error {
   262  		_, err := ge.GetCtxTestClient().CallUnaryFromUnary(ctx, CreateContextObject(ctx))
   263  		return err
   264  	})
   265  
   266  	cmdline.SetContextBuilderVersion(OLD_CONTEXT_VERSION)
   267  	t = NewTest("fork test")
   268  	ctx = authremote.Context()
   269  	_, err = ge.GetCtxTestClient().TestFork(ctx, CreateContextObject(ctx))
   270  	t.Error(err)
   271  	t.Done()
   272  
   273  	cmdline.SetContextBuilderVersion(NEW_CONTEXT_VERSION)
   274  	t = NewTest("fork test")
   275  	ctx = authremote.Context()
   276  	_, err = ge.GetCtxTestClient().TestFork(ctx, CreateContextObject(ctx))
   277  	t.Error(err)
   278  	t.Done()
   279  
   280  	cmdline.SetContextBuilderVersion(OLD_CONTEXT_VERSION)
   281  	t = NewTest("(de)serialise")
   282  	ctx = authremote.Context()
   283  	_, err = ge.GetCtxTestClient().TestDeSer(ctx, CreateContextObject(ctx))
   284  	t.Error(err)
   285  	t.Done()
   286  
   287  	cmdline.SetContextBuilderVersion(NEW_CONTEXT_VERSION)
   288  	t = NewTest("(de)serialise")
   289  	ctx = authremote.Context()
   290  	dctx, err := ge.GetCtxTestClient().TestDeSer(ctx, CreateContextObject(ctx))
   291  	t.Error(err)
   292  	t.Done()
   293  
   294  	if dctx != nil {
   295  		cmdline.SetContextBuilderVersion(NEW_CONTEXT_VERSION)
   296  		t = NewTest("use serialised context to access service")
   297  		if !pctx.IsSerialisedByBuilder(dctx.Data) {
   298  			t.Error(fmt.Errorf("ctx failed to recognise it as a context"))
   299  		}
   300  		ctx, err = pctx.DeserialiseContext(dctx.Data)
   301  		t.Error(err)
   302  	}
   303  	dctx, err = ge.GetCtxTestClient().TestDeSer(ctx, CreateContextObject(ctx))
   304  	t.Error(err)
   305  	if dctx == nil || (!CompareUsers(dctx.User, auth.GetSignedUser(ctx))) {
   306  		t.Error(fmt.Errorf("No user in service with serialised context"))
   307  	}
   308  	t.Done()
   309  
   310  	if dctx != nil {
   311  		cmdline.SetContextBuilderVersion(OLD_CONTEXT_VERSION)
   312  		t = NewTest("use serialised context to access service")
   313  		if !pctx.IsSerialisedByBuilder(dctx.Data) {
   314  			t.Error(fmt.Errorf("ctx failed to recognise it as a context"))
   315  		}
   316  		ctx, err = pctx.DeserialiseContext(dctx.Data)
   317  		t.Error(err)
   318  	}
   319  	dctx, err = ge.GetCtxTestClient().TestDeSer(ctx, CreateContextObject(ctx))
   320  	t.Error(err)
   321  	if dctx == nil || (!CompareUsers(dctx.User, auth.GetSignedUser(ctx))) {
   322  		t.Error(fmt.Errorf("No user in service with serialised context"))
   323  	}
   324  	t.Done()
   325  
   326  	cmdline.SetContextBuilderVersion(OLD_CONTEXT_VERSION)
   327  	t = NewTest("serialise old, deserialise new")
   328  	ctx = authremote.Context()
   329  	r, err := ge.GetCtxTestClient().TestDeSer(ctx, CreateContextObject(ctx))
   330  	t.Error(err)
   331  	if err == nil {
   332  		cmdline.SetContextBuilderVersion(NEW_CONTEXT_VERSION)
   333  		nctx, err := auth.RecreateContextWithTimeout(time.Duration(10)*time.Second, r.Data)
   334  		t.Error(err)
   335  		if err != nil {
   336  			err = AssertEqualContexts(ctx, nctx)
   337  			t.Error(err)
   338  		}
   339  	}
   340  	t.Done()
   341  
   342  	//	fmt.Printf("a\n")
   343  	cmdline.SetContextBuilderVersion(OLD_CONTEXT_VERSION)
   344  	t = NewTest("old context, call new service")
   345  	ctx = authremote.Context()
   346  	cmdline.SetContextBuilderVersion(NEW_CONTEXT_VERSION)
   347  	//	fmt.Printf("c\n")
   348  	_, err = ge.GetCtxTestClient().TestDeSer(ctx, CreateContextObject(ctx))
   349  	t.Error(err)
   350  	t.Done()
   351  
   352  }
   353  
   354  func AssertEqualContexts(ctx1, ctx2 context.Context) error {
   355  	su1 := auth.GetSignedUser(ctx1)
   356  	su2 := auth.GetSignedUser(ctx2)
   357  	if !CompareUsers(su1, su2) {
   358  		u1 := gcm.VerifySignedUser(su1)
   359  		u2 := gcm.VerifySignedUser(su2)
   360  		return fmt.Errorf("u1 (%s) != u2 (%s)", auth.UserIDString(u1), auth.UserIDString(u2))
   361  	}
   362  
   363  	return nil
   364  }
   365  
   366  func CompareUsers(su1, su2 *apb.SignedUser) bool {
   367  	u1 := gcm.VerifySignedUser(su1)
   368  	u2 := gcm.VerifySignedUser(su2)
   369  	if u1 == nil && u2 == nil {
   370  		return true
   371  	}
   372  	if u1 == nil && u2 != nil {
   373  		return false
   374  	}
   375  	if u1 != nil && u2 == nil {
   376  		return false
   377  	}
   378  
   379  	if u1.ID != u2.ID {
   380  		return false
   381  	}
   382  	return true
   383  }
   384  
   385  type recv interface {
   386  	Recv() (*common.Void, error)
   387  }
   388  
   389  func checkSrv(r recv) error {
   390  	for {
   391  		_, err := r.Recv()
   392  		if err == io.EOF {
   393  			return nil
   394  		}
   395  		if err != nil {
   396  			return err
   397  		}
   398  	}
   399  }
   400  
   401  func checkStream(name string, f func(ctx context.Context) (recv, error)) {
   402  	cmdline.SetContextBuilderVersion(NEW_CONTEXT_VERSION)
   403  	t := NewTest("stream-bouncer %s (new ctx)", name)
   404  	ctx := authremote.Context()
   405  	srv, err := f(ctx)
   406  	t.Error(err)
   407  	t.Error(checkSrv(srv))
   408  	t.Done()
   409  
   410  	cmdline.SetContextBuilderVersion(OLD_CONTEXT_VERSION)
   411  	t = NewTest("stream-bouncer %s (old ctx)", name)
   412  	ctx = authremote.Context()
   413  	srv, err = f(ctx)
   414  	t.Error(err)
   415  	t.Error(checkSrv(srv))
   416  	t.Done()
   417  
   418  	cmdline.SetContextBuilderVersion(NEW_CONTEXT_VERSION)
   419  	ctx = authremote.Context()
   420  	t = NewTest("stream-bouncer %s (new/old ctx)", name)
   421  	cmdline.SetContextBuilderVersion(OLD_CONTEXT_VERSION)
   422  	srv, err = f(ctx)
   423  	t.Error(err)
   424  	t.Error(checkSrv(srv))
   425  	t.Done()
   426  
   427  	cmdline.SetContextBuilderVersion(OLD_CONTEXT_VERSION)
   428  	ctx = authremote.Context()
   429  	t = NewTest("stream-bouncer %s (old/new ctx)", name)
   430  	cmdline.SetContextBuilderVersion(NEW_CONTEXT_VERSION)
   431  	srv, err = f(ctx)
   432  	t.Error(err)
   433  	t.Error(checkSrv(srv))
   434  	t.Done()
   435  
   436  }
   437  func checkUnary(name string, f func(ctx context.Context) error) {
   438  	cmdline.SetContextBuilderVersion(NEW_CONTEXT_VERSION)
   439  	t := NewTest("unary-bouncer with_cb %s (new ctx)", name)
   440  	ctx := authremote.Context()
   441  	err := f(ctx)
   442  	t.Error(err)
   443  	t.Done()
   444  
   445  	cmdline.SetContextBuilderVersion(OLD_CONTEXT_VERSION)
   446  	t = NewTest("unary-bouncer wo_cb %s (old ctx)", name)
   447  	ctx = authremote.Context()
   448  	err = f(ctx)
   449  	t.Error(err)
   450  	t.Done()
   451  
   452  	cmdline.SetContextBuilderVersion(NEW_CONTEXT_VERSION)
   453  	t = NewTest("unary-bouncer %s cb_tf (new/old ctx)", name)
   454  	ctx = authremote.Context()
   455  	cmdline.SetContextBuilderVersion(OLD_CONTEXT_VERSION)
   456  	err = f(ctx)
   457  	t.Error(err)
   458  	t.Done()
   459  
   460  	cmdline.SetContextBuilderVersion(OLD_CONTEXT_VERSION)
   461  	t = NewTest("unary-bouncer %s cb_ft test (old/new ctx)", name)
   462  	ctx = authremote.Context()
   463  	cmdline.SetContextBuilderVersion(NEW_CONTEXT_VERSION)
   464  	err = f(ctx)
   465  	t.Error(err)
   466  	t.Done()
   467  
   468  }
   469  
   470  func CreateContextObject(ctx context.Context) *ge.RequiredContext {
   471  	res := &ge.RequiredContext{
   472  		User:    auth.GetSignedUser(ctx),
   473  		Service: auth.GetSignedService(ctx),
   474  	}
   475  	return res
   476  }
   477  func AssertRequiredContext(ctx context.Context, rc *ge.RequiredContext) error {
   478  	if ctx == nil {
   479  		return fmt.Errorf("no context to assert")
   480  	}
   481  	u := auth.GetSignedUser(ctx)
   482  	s := auth.GetSignedService(ctx)
   483  	err := AssertSameUser("user", rc.User, u)
   484  	if err != nil {
   485  		fmt.Println("Mismatched context:" + pctx.Context2String(ctx))
   486  		return err
   487  	}
   488  	if rc.Service != nil {
   489  		err = AssertSameUser("service", rc.Service, s)
   490  		if err != nil {
   491  			fmt.Println("Mismatched context:" + pctx.Context2String(ctx))
   492  			return err
   493  		}
   494  	}
   495  	return nil
   496  }
   497  func AssertSameUser(s string, u1, u2 *apb.SignedUser) error {
   498  	if !CompareUsers(u1, u2) {
   499  		uu1 := gcm.VerifySignedUser(u1)
   500  		uu2 := gcm.VerifySignedUser(u2)
   501  		utils.PrintStack("%s Mismatch: expected=%s, actual=%s", s, auth.UserIDString(uu1), auth.UserIDString(uu2))
   502  		return fmt.Errorf("%s Mismatch: expected=%s, actual=%s", s, auth.UserIDString(uu1), auth.UserIDString(uu2))
   503  	}
   504  	return nil
   505  }
   506  

View as plain text