github.com/iron-io/functions@v0.0.0-20180820112432-d59d7d1c40b2/api/datastore/internal/datastoretest/test.go (about)

     1  package datastoretest
     2  
     3  import (
     4  	"bytes"
     5  	"context"
     6  	"log"
     7  	"testing"
     8  
     9  	"github.com/iron-io/functions/api/models"
    10  
    11  	"net/http"
    12  	"net/url"
    13  	"os"
    14  	"reflect"
    15  
    16  	"github.com/Sirupsen/logrus"
    17  	"github.com/gin-gonic/gin"
    18  )
    19  
    20  func setLogBuffer() *bytes.Buffer {
    21  	var buf bytes.Buffer
    22  	buf.WriteByte('\n')
    23  	logrus.SetOutput(&buf)
    24  	gin.DefaultErrorWriter = &buf
    25  	gin.DefaultWriter = &buf
    26  	log.SetOutput(&buf)
    27  	return &buf
    28  }
    29  
    30  func GetContainerHostIP() string {
    31  	dockerHost := os.Getenv("DOCKER_HOST")
    32  	if dockerHost == "" {
    33  		return "127.0.0.1"
    34  	}
    35  	parts, _ := url.Parse(dockerHost)
    36  	return parts.Hostname()
    37  }
    38  
    39  func Test(t *testing.T, ds models.Datastore) {
    40  	buf := setLogBuffer()
    41  
    42  	ctx := context.Background()
    43  
    44  	t.Run("apps", func(t *testing.T) {
    45  		// Testing insert app
    46  		_, err := ds.InsertApp(ctx, nil)
    47  		if err != models.ErrDatastoreEmptyApp {
    48  			t.Log(buf.String())
    49  			t.Fatalf("Test InsertApp(nil): expected error `%v`, but it was `%v`", models.ErrDatastoreEmptyApp, err)
    50  		}
    51  
    52  		_, err = ds.InsertApp(ctx, &models.App{})
    53  		if err != models.ErrDatastoreEmptyAppName {
    54  			t.Log(buf.String())
    55  			t.Fatalf("Test InsertApp(&{}): expected error `%v`, but it was `%v`", models.ErrDatastoreEmptyAppName, err)
    56  		}
    57  
    58  		inserted, err := ds.InsertApp(ctx, testApp)
    59  		if err != nil {
    60  			t.Log(buf.String())
    61  			t.Fatalf("Test InsertApp: error when storing new app: %s", err)
    62  		}
    63  		if !reflect.DeepEqual(*inserted, *testApp) {
    64  			t.Log(buf.String())
    65  			t.Fatalf("Test InsertApp: expected to insert:\n%v\nbut got:\n%v", testApp, inserted)
    66  		}
    67  
    68  		_, err = ds.InsertApp(ctx, testApp)
    69  		if err != models.ErrAppsAlreadyExists {
    70  			t.Log(buf.String())
    71  			t.Fatalf("Test InsertApp duplicated: expected error `%v`, but it was `%v`", models.ErrAppsAlreadyExists, err)
    72  		}
    73  
    74  		{
    75  			// Set a config var
    76  			updated, err := ds.UpdateApp(ctx,
    77  				&models.App{Name: testApp.Name, Config: map[string]string{"TEST": "1"}})
    78  			if err != nil {
    79  				t.Log(buf.String())
    80  				t.Fatalf("Test UpdateApp: error when updating app: %v", err)
    81  			}
    82  			expected := &models.App{Name: testApp.Name, Config: map[string]string{"TEST": "1"}}
    83  			if !reflect.DeepEqual(*updated, *expected) {
    84  				t.Log(buf.String())
    85  				t.Fatalf("Test UpdateApp: expected updated `%v` but got `%v`", expected, updated)
    86  			}
    87  
    88  			// Set a different var (without clearing the existing)
    89  			updated, err = ds.UpdateApp(ctx,
    90  				&models.App{Name: testApp.Name, Config: map[string]string{"OTHER": "TEST"}})
    91  			if err != nil {
    92  				t.Log(buf.String())
    93  				t.Fatalf("Test UpdateApp: error when updating app: %v", err)
    94  			}
    95  			expected = &models.App{Name: testApp.Name, Config: map[string]string{"TEST": "1", "OTHER": "TEST"}}
    96  			if !reflect.DeepEqual(*updated, *expected) {
    97  				t.Log(buf.String())
    98  				t.Fatalf("Test UpdateApp: expected updated `%v` but got `%v`", expected, updated)
    99  			}
   100  
   101  			// Delete a var
   102  			updated, err = ds.UpdateApp(ctx,
   103  				&models.App{Name: testApp.Name, Config: map[string]string{"TEST": ""}})
   104  			if err != nil {
   105  				t.Log(buf.String())
   106  				t.Fatalf("Test UpdateApp: error when updating app: %v", err)
   107  			}
   108  			expected = &models.App{Name: testApp.Name, Config: map[string]string{"OTHER": "TEST"}}
   109  			if !reflect.DeepEqual(*updated, *expected) {
   110  				t.Log(buf.String())
   111  				t.Fatalf("Test UpdateApp: expected updated `%v` but got `%v`", expected, updated)
   112  			}
   113  		}
   114  
   115  		// Testing get app
   116  		_, err = ds.GetApp(ctx, "")
   117  		if err != models.ErrDatastoreEmptyAppName {
   118  			t.Log(buf.String())
   119  			t.Fatalf("Test GetApp: expected error to be %v, but it was %s", models.ErrDatastoreEmptyAppName, err)
   120  		}
   121  
   122  		app, err := ds.GetApp(ctx, testApp.Name)
   123  		if err != nil {
   124  			t.Log(buf.String())
   125  			t.Fatalf("Test GetApp: error: %s", err)
   126  		}
   127  		if app.Name != testApp.Name {
   128  			t.Log(buf.String())
   129  			t.Fatalf("Test GetApp: expected `app.Name` to be `%s` but it was `%s`", app.Name, testApp.Name)
   130  		}
   131  
   132  		// Testing list apps
   133  		apps, err := ds.GetApps(ctx, &models.AppFilter{})
   134  		if err != nil {
   135  			t.Log(buf.String())
   136  			t.Fatalf("Test GetApps: unexpected error %v", err)
   137  		}
   138  		if len(apps) == 0 {
   139  			t.Fatal("Test GetApps: expected result count to be greater than 0")
   140  		}
   141  		if apps[0].Name != testApp.Name {
   142  			t.Log(buf.String())
   143  			t.Fatalf("Test GetApps: expected `app.Name` to be `%s` but it was `%s`", app.Name, testApp.Name)
   144  		}
   145  
   146  		apps, err = ds.GetApps(ctx, &models.AppFilter{Name: "Tes%"})
   147  		if err != nil {
   148  			t.Log(buf.String())
   149  			t.Fatalf("Test GetApps(filter): unexpected error %v", err)
   150  		}
   151  		if len(apps) == 0 {
   152  			t.Fatal("Test GetApps(filter): expected result count to be greater than 0")
   153  		}
   154  
   155  		// Testing app delete
   156  		err = ds.RemoveApp(ctx, "")
   157  		if err != models.ErrDatastoreEmptyAppName {
   158  			t.Log(buf.String())
   159  			t.Fatalf("Test RemoveApp: expected error `%v`, but it was `%v`", models.ErrDatastoreEmptyAppName, err)
   160  		}
   161  
   162  		err = ds.RemoveApp(ctx, testApp.Name)
   163  		if err != nil {
   164  			t.Log(buf.String())
   165  			t.Fatalf("Test RemoveApp: error: %s", err)
   166  		}
   167  		app, err = ds.GetApp(ctx, testApp.Name)
   168  		if err != models.ErrAppsNotFound {
   169  			t.Log(buf.String())
   170  			t.Fatalf("Test GetApp(removed): expected error `%v`, but it was `%v`", models.ErrAppsNotFound, err)
   171  		}
   172  		if app != nil {
   173  			t.Log(buf.String())
   174  			t.Fatal("Test RemoveApp: failed to remove the app")
   175  		}
   176  
   177  		// Test update inexistent app
   178  		_, err = ds.UpdateApp(ctx, &models.App{
   179  			Name: testApp.Name,
   180  			Config: map[string]string{
   181  				"TEST": "1",
   182  			},
   183  		})
   184  		if err != models.ErrAppsNotFound {
   185  			t.Log(buf.String())
   186  			t.Fatalf("Test UpdateApp(inexistent): expected error `%v`, but it was `%v`", models.ErrAppsNotFound, err)
   187  		}
   188  	})
   189  
   190  	t.Run("routes", func(t *testing.T) {
   191  		// Insert app again to test routes
   192  		_, err := ds.InsertApp(ctx, testApp)
   193  		if err != nil && err != models.ErrAppsAlreadyExists {
   194  			t.Log(buf.String())
   195  			t.Fatalf("Test InsertRoute Prep: failed to insert app: ", err)
   196  		}
   197  
   198  		// Testing insert route
   199  		{
   200  			_, err = ds.InsertRoute(ctx, nil)
   201  			if err != models.ErrDatastoreEmptyRoute {
   202  				t.Log(buf.String())
   203  				t.Fatalf("Test InsertRoute(nil): expected error `%v`, but it was `%v`", models.ErrDatastoreEmptyRoute, err)
   204  			}
   205  
   206  			_, err = ds.InsertRoute(ctx, &models.Route{AppName: "notreal", Path: "/test"})
   207  			if err != models.ErrAppsNotFound {
   208  				t.Log(buf.String())
   209  				t.Fatalf("Test InsertRoute: expected error `%v`, but it was `%v`", models.ErrAppsNotFound, err)
   210  			}
   211  
   212  			_, err = ds.InsertRoute(ctx, testRoute)
   213  			if err != nil {
   214  				t.Log(buf.String())
   215  				t.Fatalf("Test InsertRoute: error when storing new route: %s", err)
   216  			}
   217  
   218  			_, err = ds.InsertRoute(ctx, testRoute)
   219  			if err != models.ErrRoutesAlreadyExists {
   220  				t.Log(buf.String())
   221  				t.Fatalf("Test InsertRoute duplicated: expected error to be `%v`, but it was `%v`", models.ErrRoutesAlreadyExists, err)
   222  			}
   223  		}
   224  
   225  		// Testing get
   226  		{
   227  			_, err = ds.GetRoute(ctx, "a", "")
   228  			if err != models.ErrDatastoreEmptyRoutePath {
   229  				t.Log(buf.String())
   230  				t.Fatalf("Test GetRoute(empty route path): expected error `%v`, but it was `%v`", models.ErrDatastoreEmptyRoutePath, err)
   231  			}
   232  
   233  			_, err = ds.GetRoute(ctx, "", "a")
   234  			if err != models.ErrDatastoreEmptyAppName {
   235  				t.Log(buf.String())
   236  				t.Fatalf("Test GetRoute(empty app name): expected error `%v`, but it was `%v`", models.ErrDatastoreEmptyAppName, err)
   237  			}
   238  
   239  			route, err := ds.GetRoute(ctx, testApp.Name, testRoute.Path)
   240  			if err != nil {
   241  				t.Log(buf.String())
   242  				t.Fatalf("Test GetRoute: unexpected error %v", err)
   243  			}
   244  			var expected models.Route = *testRoute
   245  			if !reflect.DeepEqual(*route, expected) {
   246  				t.Log(buf.String())
   247  				t.Fatalf("Test InsertApp: expected to insert:\n%v\nbut got:\n%v", expected, route)
   248  			}
   249  		}
   250  
   251  		// Testing update
   252  		{
   253  			// Update some fields, and add 3 configs and 3 headers.
   254  			updated, err := ds.UpdateRoute(ctx, &models.Route{
   255  				AppName: testRoute.AppName,
   256  				Path:    testRoute.Path,
   257  				Timeout: 100,
   258  				Config: map[string]string{
   259  					"FIRST":  "1",
   260  					"SECOND": "2",
   261  					"THIRD":  "3",
   262  				},
   263  				Headers: http.Header{
   264  					"First":  []string{"test"},
   265  					"Second": []string{"test", "test"},
   266  					"Third":  []string{"test", "test2"},
   267  				},
   268  			})
   269  			if err != nil {
   270  				t.Log(buf.String())
   271  				t.Fatalf("Test UpdateRoute: unexpected error: %v", err)
   272  			}
   273  			expected := &models.Route{
   274  				// unchanged
   275  				AppName: testRoute.AppName,
   276  				Path:    testRoute.Path,
   277  				Image:   "iron/hello",
   278  				Type:    "sync",
   279  				Format:  "http",
   280  				// updated
   281  				Timeout: 100,
   282  				Config: map[string]string{
   283  					"FIRST":  "1",
   284  					"SECOND": "2",
   285  					"THIRD":  "3",
   286  				},
   287  				Headers: http.Header{
   288  					"First":  []string{"test"},
   289  					"Second": []string{"test", "test"},
   290  					"Third":  []string{"test", "test2"},
   291  				},
   292  			}
   293  			if !reflect.DeepEqual(*updated, *expected) {
   294  				t.Log(buf.String())
   295  				t.Fatalf("Test UpdateRoute: expected updated `%v` but got `%v`", expected, updated)
   296  			}
   297  
   298  			// Update a config var, remove another. Add one Header, remove another.
   299  			updated, err = ds.UpdateRoute(ctx, &models.Route{
   300  				AppName: testRoute.AppName,
   301  				Path:    testRoute.Path,
   302  				Config: map[string]string{
   303  					"FIRST":  "first",
   304  					"SECOND": "",
   305  					"THIRD":  "3",
   306  				},
   307  				Headers: http.Header{
   308  					"First":  []string{"test2"},
   309  					"Second": nil,
   310  				},
   311  			})
   312  			if err != nil {
   313  				t.Log(buf.String())
   314  				t.Fatalf("Test UpdateRoute: unexpected error: %v", err)
   315  			}
   316  			expected = &models.Route{
   317  				// unchanged
   318  				AppName: testRoute.AppName,
   319  				Path:    testRoute.Path,
   320  				Image:   "iron/hello",
   321  				Type:    "sync",
   322  				Format:  "http",
   323  				Timeout: 100,
   324  				// updated
   325  				Config: map[string]string{
   326  					"FIRST": "first",
   327  					"THIRD": "3",
   328  				},
   329  				Headers: http.Header{
   330  					"First": []string{"test", "test2"},
   331  					"Third": []string{"test", "test2"},
   332  				},
   333  			}
   334  			if !reflect.DeepEqual(*updated, *expected) {
   335  				t.Log(buf.String())
   336  				t.Fatalf("Test UpdateRoute: expected updated:\n`%v`\nbut got:\n`%v`", expected, updated)
   337  			}
   338  		}
   339  
   340  		// Testing list routes
   341  		routes, err := ds.GetRoutesByApp(ctx, testApp.Name, &models.RouteFilter{})
   342  		if err != nil {
   343  			t.Log(buf.String())
   344  			t.Fatalf("Test GetRoutesByApp: unexpected error %v", err)
   345  		}
   346  		if len(routes) == 0 {
   347  			t.Fatal("Test GetRoutesByApp: expected result count to be greater than 0")
   348  		}
   349  		if routes[0] == nil {
   350  			t.Log(buf.String())
   351  			t.Fatalf("Test GetRoutes: expected non-nil route")
   352  		} else if routes[0].Path != testRoute.Path {
   353  			t.Log(buf.String())
   354  			t.Fatalf("Test GetRoutes: expected `app.Name` to be `%s` but it was `%s`", testRoute.Path, routes[0].Path)
   355  		}
   356  
   357  		routes, err = ds.GetRoutesByApp(ctx, testApp.Name, &models.RouteFilter{Image: testRoute.Image})
   358  		if err != nil {
   359  			t.Log(buf.String())
   360  			t.Fatalf("Test GetRoutesByApp: unexpected error %v", err)
   361  		}
   362  		if len(routes) == 0 {
   363  			t.Fatal("Test GetRoutesByApp: expected result count to be greater than 0")
   364  		}
   365  		if routes[0] == nil {
   366  			t.Log(buf.String())
   367  			t.Fatalf("Test GetRoutes: expected non-nil route")
   368  		} else if routes[0].Path != testRoute.Path {
   369  			t.Log(buf.String())
   370  			t.Fatalf("Test GetRoutes: expected `app.Name` to be `%s` but it was `%s`", testRoute.Path, routes[0].Path)
   371  		}
   372  
   373  		routes, err = ds.GetRoutesByApp(ctx, "notreal", nil)
   374  		if err != nil {
   375  			t.Log(buf.String())
   376  			t.Fatalf("Test GetRoutesByApp: error: %s", err)
   377  		}
   378  		if len(routes) != 0 {
   379  			t.Fatalf("Test GetRoutesByApp: expected result count to be 0 but got %d", len(routes))
   380  		}
   381  
   382  		// Testing list routes
   383  		routes, err = ds.GetRoutes(ctx, &models.RouteFilter{Image: testRoute.Image})
   384  		if err != nil {
   385  			t.Log(buf.String())
   386  			t.Fatalf("Test GetRoutes: error: %s", err)
   387  		}
   388  		if len(routes) == 0 {
   389  			t.Fatal("Test GetRoutes: expected result count to be greater than 0")
   390  		}
   391  		if routes[0].Path != testRoute.Path {
   392  			t.Log(buf.String())
   393  			t.Fatalf("Test GetRoutes: expected `app.Name` to be `%s` but it was `%s`", testRoute.Path, routes[0].Path)
   394  		}
   395  
   396  		// Testing route delete
   397  		err = ds.RemoveRoute(ctx, "", "")
   398  		if err != models.ErrDatastoreEmptyAppName {
   399  			t.Log(buf.String())
   400  			t.Fatalf("Test RemoveRoute(empty app name): expected error `%v`, but it was `%v`", models.ErrDatastoreEmptyAppName, err)
   401  		}
   402  
   403  		err = ds.RemoveRoute(ctx, "a", "")
   404  		if err != models.ErrDatastoreEmptyRoutePath {
   405  			t.Log(buf.String())
   406  			t.Fatalf("Test RemoveRoute(empty route path): expected error `%v`, but it was `%v`", models.ErrDatastoreEmptyRoutePath, err)
   407  		}
   408  
   409  		err = ds.RemoveRoute(ctx, testRoute.AppName, testRoute.Path)
   410  		if err != nil {
   411  			t.Log(buf.String())
   412  			t.Fatalf("Test RemoveApp: unexpected error: %v", err)
   413  		}
   414  
   415  		route, err := ds.GetRoute(ctx, testRoute.AppName, testRoute.Path)
   416  		if err != nil && err != models.ErrRoutesNotFound {
   417  			t.Log(buf.String())
   418  			t.Fatalf("Test GetRoute: expected error `%v`, but it was `%v`", models.ErrRoutesNotFound, err)
   419  		}
   420  		if route != nil {
   421  			t.Log(buf.String())
   422  			t.Fatalf("Test RemoveApp: failed to remove the route: %v", route)
   423  		}
   424  
   425  		_, err = ds.UpdateRoute(ctx, &models.Route{
   426  			AppName: testRoute.AppName,
   427  			Path:    testRoute.Path,
   428  			Image:   "test",
   429  		})
   430  		if err != models.ErrRoutesNotFound {
   431  			t.Log(buf.String())
   432  			t.Fatalf("Test UpdateRoute inexistent: expected error to be `%v`, but it was `%v`", models.ErrRoutesNotFound, err)
   433  		}
   434  	})
   435  
   436  	t.Run("put-get", func(t *testing.T) {
   437  		// Testing Put/Get
   438  		err := ds.Put(ctx, nil, nil)
   439  		if err != models.ErrDatastoreEmptyKey {
   440  			t.Log(buf.String())
   441  			t.Fatalf("Test Put(nil,nil): expected error `%v`, but it was `%v`", models.ErrDatastoreEmptyKey, err)
   442  		}
   443  
   444  		err = ds.Put(ctx, []byte("test"), []byte("success"))
   445  		if err != nil {
   446  			t.Log(buf.String())
   447  			t.Fatalf("Test Put: unexpected error: %v", err)
   448  		}
   449  
   450  		val, err := ds.Get(ctx, []byte("test"))
   451  		if err != nil {
   452  			t.Log(buf.String())
   453  			t.Fatalf("Test Put: unexpected error: %v", err)
   454  		}
   455  		if string(val) != "success" {
   456  			t.Log(buf.String())
   457  			t.Fatalf("Test Get: expected value to be `%v`, but it was `%v`", "success", string(val))
   458  		}
   459  
   460  		err = ds.Put(ctx, []byte("test"), nil)
   461  		if err != nil {
   462  			t.Log(buf.String())
   463  			t.Fatalf("Test Put: unexpected error: %v", err)
   464  		}
   465  
   466  		val, err = ds.Get(ctx, []byte("test"))
   467  		if err != nil {
   468  			t.Log(buf.String())
   469  			t.Fatalf("Test Put: unexpected error: %v", err)
   470  		}
   471  		if string(val) != "" {
   472  			t.Log(buf.String())
   473  			t.Fatalf("Test Get: expected value to be `%v`, but it was `%v`", "", string(val))
   474  		}
   475  	})
   476  }
   477  
   478  var testApp = &models.App{
   479  	Name: "Test",
   480  }
   481  
   482  var testRoute = &models.Route{
   483  	AppName: testApp.Name,
   484  	Path:    "/test",
   485  	Image:   "iron/hello",
   486  	Type:    "sync",
   487  	Format:  "http",
   488  }