github.com/tickoalcantara12/micro/v3@v3.0.0-20221007104245-9d75b9bcbab9/test/runtime_test.go (about)

     1  //go:build integration
     2  // +build integration
     3  
     4  package test
     5  
     6  import (
     7  	"encoding/json"
     8  	"errors"
     9  	"fmt"
    10  	"io/ioutil"
    11  	"os"
    12  	"os/exec"
    13  	"os/user"
    14  	"path/filepath"
    15  	"strings"
    16  	"testing"
    17  	"time"
    18  )
    19  
    20  const (
    21  	branch  = ""
    22  	version = "latest"
    23  )
    24  
    25  func TestServerModeCall(t *testing.T) {
    26  	TrySuite(t, ServerModeCall, retryCount)
    27  }
    28  
    29  func ServerModeCall(t *T) {
    30  	t.Parallel()
    31  	serv := NewServer(t, WithLogin())
    32  
    33  	cmd := serv.Command()
    34  
    35  	outp, err := cmd.Exec("call", "runtime", "Runtime.Read", "{}")
    36  	if err == nil {
    37  		t.Fatalf("Call to server should fail, got no error, output: %v", string(outp))
    38  		return
    39  	}
    40  
    41  	defer serv.Close()
    42  	if err := serv.Run(); err != nil {
    43  		return
    44  	}
    45  
    46  	if err := Try("Calling Runtime.Read", t, func() ([]byte, error) {
    47  		outp, err := cmd.Exec("call", "runtime", "Runtime.Read", "{}")
    48  		if err != nil {
    49  			return outp, errors.New("Call to runtime read should succeed")
    50  		}
    51  		return outp, err
    52  	}, 5*time.Second); err != nil {
    53  		return
    54  	}
    55  }
    56  
    57  func TestRunLocalSource(t *testing.T) {
    58  	TrySuite(t, testRunLocalSource, retryCount)
    59  }
    60  
    61  func testRunLocalSource(t *T) {
    62  	t.Parallel()
    63  	serv := NewServer(t, WithLogin())
    64  	defer serv.Close()
    65  	if err := serv.Run(); err != nil {
    66  		return
    67  	}
    68  
    69  	cmd := serv.Command()
    70  
    71  	outp, err := cmd.Exec("run", "./services/helloworld")
    72  	if err != nil {
    73  		t.Fatalf("micro run failure, output: %v", string(outp))
    74  		return
    75  	}
    76  
    77  	if err := Try("Find helloworld", t, func() ([]byte, error) {
    78  		outp, err := cmd.Exec("status")
    79  		if err != nil {
    80  			return outp, err
    81  		}
    82  
    83  		if !statusRunning("helloworld", "latest", outp) {
    84  			return outp, errors.New("Can't find helloworld service in runtime")
    85  		}
    86  		return outp, err
    87  	}, 15*time.Second); err != nil {
    88  		return
    89  	}
    90  
    91  	if err := Try("Find helloworld in list", t, func() ([]byte, error) {
    92  		outp, err := cmd.Exec("services")
    93  		if err != nil {
    94  			return outp, err
    95  		}
    96  		if !strings.Contains(string(outp), "helloworld") {
    97  			return outp, errors.New("Can't find example service in list")
    98  		}
    99  		return outp, err
   100  	}, 90*time.Second); err != nil {
   101  		return
   102  	}
   103  }
   104  
   105  func TestRunAndKill(t *testing.T) {
   106  	TrySuite(t, testRunAndKill, retryCount)
   107  }
   108  
   109  func testRunAndKill(t *T) {
   110  	t.Parallel()
   111  	serv := NewServer(t, WithLogin())
   112  	defer serv.Close()
   113  	if err := serv.Run(); err != nil {
   114  		return
   115  	}
   116  
   117  	cmd := serv.Command()
   118  
   119  	outp, err := cmd.Exec("run", "./services/helloworld")
   120  	if err != nil {
   121  		t.Fatalf("micro run failure, output: %v", string(outp))
   122  		return
   123  	}
   124  
   125  	if err := Try("Find helloworld", t, func() ([]byte, error) {
   126  		outp, err = cmd.Exec("status")
   127  		if err != nil {
   128  			return outp, err
   129  		}
   130  
   131  		if !statusRunning("helloworld", "latest", outp) {
   132  			return outp, errors.New("Can't find example service in runtime")
   133  		}
   134  		return outp, err
   135  	}, 30*time.Second); err != nil {
   136  		return
   137  	}
   138  
   139  	if err := Try("Find helloworld in list", t, func() ([]byte, error) {
   140  		outp, err := cmd.Exec("services")
   141  		if err != nil {
   142  			return outp, err
   143  		}
   144  		if !strings.Contains(string(outp), "helloworld") {
   145  			outp1, _ := cmd.Exec("logs", "helloworld")
   146  			return append(outp, outp1...), errors.New("Can't find helloworld service in list")
   147  		}
   148  		return outp, err
   149  	}, 90*time.Second); err != nil {
   150  		return
   151  	}
   152  
   153  	outp, err = cmd.Exec("kill", "helloworld")
   154  	if err != nil {
   155  		t.Fatalf("micro kill failure, output: %v", string(outp))
   156  		return
   157  	}
   158  
   159  	if err := Try("Find helloworld", t, func() ([]byte, error) {
   160  		outp, err = cmd.Exec("status")
   161  		if err != nil {
   162  			return outp, err
   163  		}
   164  
   165  		// The started service should have the runtime name of "service/example",
   166  		// as the runtime name is the relative path inside a repo.
   167  		if strings.Contains(string(outp), "helloworld") {
   168  			return outp, errors.New("Should not find example service in runtime")
   169  		}
   170  		return outp, err
   171  	}, 15*time.Second); err != nil {
   172  		return
   173  	}
   174  
   175  	if err := Try("Find helloworld in list", t, func() ([]byte, error) {
   176  		outp, err := cmd.Exec("services")
   177  		if err != nil {
   178  			return outp, err
   179  		}
   180  		if strings.Contains(string(outp), "helloworld") {
   181  			return outp, errors.New("Should not find helloworld service in list")
   182  		}
   183  		return outp, err
   184  	}, 20*time.Second); err != nil {
   185  		return
   186  	}
   187  }
   188  
   189  func TestRunGithubSource(t *testing.T) {
   190  	TrySuite(t, testRunGithubSource, retryCount)
   191  }
   192  
   193  func testRunGithubSource(t *T) {
   194  	t.Parallel()
   195  
   196  	serv := NewServer(t, WithLogin())
   197  	defer serv.Close()
   198  	if err := serv.Run(); err != nil {
   199  		return
   200  	}
   201  
   202  	cmd := serv.Command()
   203  	outp, err := cmd.Exec("run", "--image", "localhost:5000/cells:v3", "github.com/micro/services/helloworld@"+branch)
   204  	if err != nil {
   205  		t.Fatalf("micro run failure, output: %v", string(outp))
   206  		return
   207  	}
   208  
   209  	if err := Try("Find helloworld in runtime", t, func() ([]byte, error) {
   210  		outp, err = cmd.Exec("status")
   211  		if err != nil {
   212  			return outp, err
   213  		}
   214  
   215  		if !statusRunning("helloworld", version, outp) {
   216  			return outp, errors.New("Output should contain helloworld")
   217  		}
   218  		if !strings.Contains(string(outp), "owner=admin") || !(strings.Contains(string(outp), "group=micro") || strings.Contains(string(outp), "group="+serv.Env())) {
   219  			return outp, errors.New("micro status does not have correct owner or group")
   220  		}
   221  		if strings.Contains(string(outp), "unknown") {
   222  			return outp, errors.New("there should be no unknown in the micro status output")
   223  		}
   224  		return outp, nil
   225  	}, 60*time.Second); err != nil {
   226  		return
   227  	}
   228  
   229  	if err := Try("Find helloworld in registry", t, func() ([]byte, error) {
   230  		outp, err = cmd.Exec("services")
   231  		if err != nil {
   232  			return outp, err
   233  		}
   234  		if !strings.Contains(string(outp), "helloworld") {
   235  			return outp, errors.New("helloworld is not running")
   236  		}
   237  		return outp, nil
   238  	}, 180*time.Second); err != nil {
   239  		return
   240  	}
   241  
   242  	if err := Try("Call helloworld", t, func() ([]byte, error) {
   243  		outp, err := cmd.Exec("call", "helloworld", "Helloworld.Call", "{\"name\":\"John\"}")
   244  		if err != nil {
   245  			return outp, err
   246  		}
   247  		rsp := map[string]string{}
   248  		err = json.Unmarshal(outp, &rsp)
   249  		if err != nil {
   250  			return outp, err
   251  		}
   252  		if rsp["message"] != "Hello John" {
   253  			return outp, errors.New("Helloworld resonse is unexpected")
   254  		}
   255  		return outp, err
   256  	}, 60*time.Second); err != nil {
   257  		return
   258  	}
   259  
   260  	cmd.Exec("kill", "helloworld")
   261  
   262  	// test it works for a branch with a funny name
   263  	outp, err = cmd.Exec("run", "--image", "localhost:5000/cells:v3", "github.com/micro/services/helloworld@integrationtest/branch_name")
   264  	if err != nil {
   265  		t.Fatalf("micro run failure, output: %v", string(outp))
   266  		return
   267  	}
   268  
   269  	if err := Try("Find helloworld in runtime", t, func() ([]byte, error) {
   270  		outp, err = cmd.Exec("status")
   271  		if err != nil {
   272  			return outp, err
   273  		}
   274  		//
   275  		if !statusRunning("helloworld", "integrationtest/branch_name", outp) {
   276  			return outp, errors.New("Output should contain helloworld")
   277  		}
   278  		if !strings.Contains(string(outp), "owner=admin") || !(strings.Contains(string(outp), "group=micro") || strings.Contains(string(outp), "group="+serv.Env())) {
   279  			return outp, errors.New("micro status does not have correct owner or group")
   280  		}
   281  		if strings.Contains(string(outp), "unknown") {
   282  			return outp, errors.New("there should be no unknown in the micro status output")
   283  		}
   284  		return outp, nil
   285  	}, 60*time.Second); err != nil {
   286  		return
   287  	}
   288  
   289  	if err := Try("Find helloworld in registry", t, func() ([]byte, error) {
   290  		outp, err = cmd.Exec("services")
   291  		if err != nil {
   292  			return outp, err
   293  		}
   294  		if !strings.Contains(string(outp), "helloworld") {
   295  			return outp, errors.New("helloworld is not running")
   296  		}
   297  		return outp, nil
   298  	}, 180*time.Second); err != nil {
   299  		return
   300  	}
   301  
   302  	if err := Try("Call helloworld", t, func() ([]byte, error) {
   303  		outp, err := cmd.Exec("call", "helloworld", "Helloworld.Call", "{\"name\":\"John\"}")
   304  		if err != nil {
   305  			return outp, err
   306  		}
   307  		rsp := map[string]string{}
   308  		err = json.Unmarshal(outp, &rsp)
   309  		if err != nil {
   310  			return outp, err
   311  		}
   312  		if rsp["msg"] != "Hello John" {
   313  			return outp, errors.New("Helloworld resonse is unexpected")
   314  		}
   315  		return outp, err
   316  	}, 60*time.Second); err != nil {
   317  		return
   318  	}
   319  
   320  }
   321  
   322  // Note: @todo this method should truly be the same as TestGithubSource.
   323  func TestRunGitlabSource(t *testing.T) {
   324  	TrySuite(t, testRunGitlabSource, retryCount)
   325  }
   326  
   327  func testRunGitlabSource(t *T) {
   328  	t.Parallel()
   329  
   330  	serv := NewServer(t, WithLogin())
   331  	defer serv.Close()
   332  	if err := serv.Run(); err != nil {
   333  		return
   334  	}
   335  
   336  	cmd := serv.Command()
   337  	cmd.Exec("user", "config", "set", "git."+serv.Env()+".baseurl", "gitlab.com/micro-test")
   338  
   339  	outp, err := cmd.Exec("run", "basic-micro-service")
   340  	if err != nil {
   341  		t.Fatalf("micro run failure, output: %v", string(outp))
   342  		return
   343  	}
   344  
   345  	if err := Try("Find basic-micro-service in runtime", t, func() ([]byte, error) {
   346  		outp, err = cmd.Exec("status")
   347  		if err != nil {
   348  			return outp, err
   349  		}
   350  
   351  		if !statusRunning("basic-micro-service", version, outp) {
   352  			return outp, errors.New("Output should contain basic-micro-service")
   353  		}
   354  		return outp, nil
   355  	}, 60*time.Second); err != nil {
   356  		return
   357  	}
   358  
   359  	if err := Try("Find example in registry", t, func() ([]byte, error) {
   360  		outp, err := cmd.Exec("services")
   361  		if err != nil {
   362  			return outp, err
   363  		}
   364  		if !strings.Contains(string(outp), "example") {
   365  			return outp, errors.New("Does not example")
   366  		}
   367  		return outp, err
   368  	}, 120*time.Second); err != nil {
   369  		outp, _ := cmd.Exec("logs", "basic-micro-service")
   370  		t.Log(string(outp))
   371  		return
   372  	}
   373  }
   374  
   375  func TestRunGitlabSourceMonoRepo(t *testing.T) {
   376  	TrySuite(t, testRunGitlabSourceMonoRepo, retryCount)
   377  }
   378  
   379  func testRunGitlabSourceMonoRepo(t *T) {
   380  	t.Parallel()
   381  
   382  	serv := NewServer(t, WithLogin())
   383  	defer serv.Close()
   384  	if err := serv.Run(); err != nil {
   385  		return
   386  	}
   387  
   388  	cmd := serv.Command()
   389  	cmd.Exec("user", "config", "set", "git."+serv.Env()+".baseurl", "gitlab.com/micro-test/monorepo-test")
   390  
   391  	outp, err := cmd.Exec("run", "subfolder-test"+branch)
   392  	if err != nil {
   393  		t.Fatalf("micro run failure, output: %v", string(outp))
   394  		return
   395  	}
   396  
   397  	if err := Try("Find helloworld in runtime", t, func() ([]byte, error) {
   398  		outp, err = cmd.Exec("status")
   399  		if err != nil {
   400  			return outp, err
   401  		}
   402  
   403  		if !statusRunning("subfolder-test", version, outp) {
   404  			return outp, errors.New("Output should contain subfolder-test")
   405  		}
   406  		return outp, nil
   407  	}, 60*time.Second); err != nil {
   408  		return
   409  	}
   410  
   411  	if err := Try("Find helloworld in registry", t, func() ([]byte, error) {
   412  		outp, err := cmd.Exec("services")
   413  		if err != nil {
   414  			return outp, err
   415  		}
   416  		if !strings.Contains(string(outp), "example") {
   417  			return outp, errors.New("Does not contain example")
   418  		}
   419  		return outp, err
   420  	}, 120*time.Second); err != nil {
   421  		outp, _ := cmd.Exec("logs", "subfolder-test")
   422  		t.Log(string(outp))
   423  		return
   424  	}
   425  }
   426  
   427  // This test exists to test the path of "generic git checkout", not just bitbucket
   428  func TestRunGenericRemote(t *testing.T) {
   429  	TrySuite(t, testRunGenericRemote, retryCount)
   430  }
   431  
   432  func testRunGenericRemote(t *T) {
   433  	t.Parallel()
   434  
   435  	serv := NewServer(t, WithLogin())
   436  	defer serv.Close()
   437  	if err := serv.Run(); err != nil {
   438  		return
   439  	}
   440  
   441  	cmd := serv.Command()
   442  	cmd.Exec("user", "config", "set", "git."+serv.Env()+".baseurl", "bitbucket.org/micro-test/monorepo-test")
   443  
   444  	outp, err := cmd.Exec("run", "subfolder-test")
   445  	if err != nil {
   446  		t.Fatalf("micro run failure, output: %v", string(outp))
   447  		return
   448  	}
   449  
   450  	if err := Try("Find subfolder-test in runtime", t, func() ([]byte, error) {
   451  		outp, err = cmd.Exec("status")
   452  		if err != nil {
   453  			return outp, err
   454  		}
   455  
   456  		if !statusRunning("subfolder-test", "latest", outp) {
   457  			return outp, errors.New("Output should contain subfolder-test")
   458  		}
   459  		return outp, nil
   460  	}, 60*time.Second); err != nil {
   461  		return
   462  	}
   463  
   464  	if err := Try("Find example in registry", t, func() ([]byte, error) {
   465  		outp, err := cmd.Exec("services")
   466  		if err != nil {
   467  			return outp, err
   468  		}
   469  		if !strings.Contains(string(outp), "example") {
   470  			return outp, errors.New("Does not contain example")
   471  		}
   472  		return outp, err
   473  	}, 120*time.Second); err != nil {
   474  		outp, _ := cmd.Exec("logs", "subfolder-test")
   475  		t.Log(string(outp))
   476  		return
   477  	}
   478  }
   479  
   480  func TestRunLocalUpdateAndCall(t *testing.T) {
   481  	TrySuite(t, testRunLocalUpdateAndCall, retryCount)
   482  }
   483  
   484  func testRunLocalUpdateAndCall(t *T) {
   485  	t.Parallel()
   486  	serv := NewServer(t, WithLogin())
   487  	defer serv.Close()
   488  	if err := serv.Run(); err != nil {
   489  		return
   490  	}
   491  
   492  	cmd := serv.Command()
   493  
   494  	// Run the example service
   495  	outp, err := cmd.Exec("run", "./services/helloworld")
   496  	if err != nil {
   497  		t.Fatalf("micro run failure, output: %v", string(outp))
   498  		return
   499  	}
   500  
   501  	if err := Try("Finding helloworld service with micro status", t, func() ([]byte, error) {
   502  		outp, err = cmd.Exec("status")
   503  		if err != nil {
   504  			return outp, err
   505  		}
   506  
   507  		// The started service should have the runtime name of "example".
   508  		if !statusRunning("helloworld", "latest", outp) {
   509  			return outp, errors.New("can't find service in runtime")
   510  		}
   511  		return outp, err
   512  	}, 15*time.Second); err != nil {
   513  		return
   514  	}
   515  
   516  	if err := Try("Call helloworld service", t, func() ([]byte, error) {
   517  		outp, err := cmd.Exec("helloworld", "--name=Joe")
   518  		if err != nil {
   519  			return outp, err
   520  		}
   521  		rsp := map[string]string{}
   522  		err = json.Unmarshal(outp, &rsp)
   523  		if err != nil {
   524  			return outp, err
   525  		}
   526  		if rsp["message"] != "Hello Joe" {
   527  			return outp, errors.New("Response is unexpected")
   528  		}
   529  		return outp, err
   530  	}, 50*time.Second); err != nil {
   531  		return
   532  	}
   533  
   534  	replaceStringInFile(t, "./services/helloworld/handler/helloworld.go", `"Hello "`, `"Hi "`)
   535  	defer func() {
   536  		// Change file back
   537  		replaceStringInFile(t, "./services/helloworld/handler/helloworld.go", `"Hi "`, `"Hello "`)
   538  	}()
   539  
   540  	outp, err = cmd.Exec("update", "./services/helloworld")
   541  	if err != nil {
   542  		t.Fatal(err)
   543  		return
   544  	}
   545  
   546  	if err := Try("Finding helloworld service with micro status", t, func() ([]byte, error) {
   547  		outp, err = cmd.Exec("status")
   548  		if err != nil {
   549  			return outp, err
   550  		}
   551  
   552  		// The started service should have the runtime name of "example".
   553  		if !statusRunning("helloworld", "latest", outp) {
   554  			outp1, _ := cmd.Exec("logs", "helloworld")
   555  			return append(outp, outp1...), errors.New("can't find service in runtime")
   556  		}
   557  		return outp, err
   558  	}, 45*time.Second); err != nil {
   559  		return
   560  	}
   561  
   562  	if err := Try("Call helloworld service after modification", t, func() ([]byte, error) {
   563  		outp, err := cmd.Exec("helloworld", "--name=Joe")
   564  		if err != nil {
   565  			outp1, _ := cmd.Exec("logs", "helloworld")
   566  			return append(outp, outp1...), err
   567  		}
   568  		rsp := map[string]string{}
   569  		err = json.Unmarshal(outp, &rsp)
   570  		if err != nil {
   571  			return outp, err
   572  		}
   573  		if rsp["message"] != "Hi Joe" {
   574  			return outp, errors.New("Response is not what's expected")
   575  		}
   576  		return outp, err
   577  	}, 45*time.Second); err != nil {
   578  		return
   579  	}
   580  }
   581  
   582  func TestRunCurrentFolder(t *testing.T) {
   583  	TrySuite(t, testRunCurrentFolder, retryCount)
   584  }
   585  
   586  func testRunCurrentFolder(t *T) {
   587  	t.Parallel()
   588  	serv := NewServer(t, WithLogin())
   589  	defer serv.Close()
   590  	if err := serv.Run(); err != nil {
   591  		return
   592  	}
   593  
   594  	cmd := serv.Command()
   595  	usr, err := user.Current()
   596  	if err != nil {
   597  		t.Fatal(err)
   598  	}
   599  	cmd.Dir = usr.HomeDir
   600  	err = os.RemoveAll(filepath.Join(usr.HomeDir, "helloworld"))
   601  	if err != nil {
   602  		t.Fatal(err)
   603  	}
   604  	//if err != nil {
   605  	//	t.Fatal(string(outp))
   606  	//}
   607  
   608  	outp, err := cmd.Exec("new", "helloworld")
   609  	if err != nil {
   610  		t.Fatal(string(outp))
   611  	}
   612  	makeProt := exec.Command("make", "proto")
   613  	makeProt.Dir = filepath.Join(usr.HomeDir, "helloworld")
   614  	outp, err = makeProt.CombinedOutput()
   615  	if err != nil {
   616  		t.Fatal(string(outp))
   617  	}
   618  
   619  	cmd.Dir = filepath.Join(usr.HomeDir, "helloworld")
   620  	outp, err = cmd.Exec("run", ".")
   621  	if err != nil {
   622  		t.Fatal(outp)
   623  	}
   624  
   625  	Try("Find helloworld", t, func() ([]byte, error) {
   626  		outp, err = cmd.Exec("status")
   627  		if !statusRunning("helloworld", "latest", outp) {
   628  			return outp, errors.New("Can't find helloworld")
   629  		}
   630  		return outp, err
   631  	}, 20*time.Second)
   632  }
   633  
   634  func TestRunParentFolder(t *testing.T) {
   635  	TrySuite(t, testRunParentFolder, retryCount)
   636  }
   637  
   638  func testRunParentFolder(t *T) {
   639  	defer func() {
   640  		os.RemoveAll("../test-top-level")
   641  	}()
   642  	t.Parallel()
   643  	serv := NewServer(t, WithLogin())
   644  	defer serv.Close()
   645  	if err := serv.Run(); err != nil {
   646  		return
   647  	}
   648  
   649  	cmd := serv.Command()
   650  	cmd.Dir = ".."
   651  	outp, err := cmd.Exec("new", "test-top-level")
   652  	if err != nil {
   653  		t.Fatal(string(outp))
   654  	}
   655  	makeProt := exec.Command("make", "proto")
   656  	makeProt.Dir = "../test-top-level"
   657  	outp, err = makeProt.CombinedOutput()
   658  	if err != nil {
   659  		t.Fatal(string(outp))
   660  	}
   661  
   662  	gomod := exec.Command("go", "mod", "edit", "-replace", "github.com/tickoalcantara12/micro/v3=github.com/tickoalcantara12/micro/v3@v3.0.0")
   663  	gomod.Dir = "../test-top-level"
   664  	if outp, err := gomod.CombinedOutput(); err != nil {
   665  		t.Fatal(string(outp))
   666  	}
   667  
   668  	err = os.MkdirAll("../parent/folder/test", 0777)
   669  	if err != nil {
   670  		t.Fatal(err)
   671  	}
   672  
   673  	cmd.Dir = "../parent/folder/test"
   674  	outp, err = cmd.Exec("run", "../../../test-top-level")
   675  	if err != nil {
   676  		t.Fatal(string(outp))
   677  	}
   678  
   679  	if err := Try("Find example", t, func() ([]byte, error) {
   680  		outp, err := cmd.Exec("status")
   681  		if err != nil {
   682  			return outp, err
   683  		}
   684  
   685  		// The started service should have the runtime name of "service/example",
   686  		// as the runtime name is the relative path inside a repo.
   687  		if !statusRunning("test-top-level", "latest", outp) {
   688  			return outp, errors.New("Can't find example service in runtime")
   689  		}
   690  		return outp, err
   691  	}, 15*time.Second); err != nil {
   692  		return
   693  	}
   694  
   695  	if err := Try("Find example in list", t, func() ([]byte, error) {
   696  		outp, err := cmd.Exec("services")
   697  		if err != nil {
   698  			return outp, err
   699  		}
   700  		if !strings.Contains(string(outp), "test-top-level") {
   701  			l, _ := cmd.Exec("logs", "test-top-level")
   702  			return outp, fmt.Errorf("Can't find example service in list. \nLogs: %v", string(l))
   703  		}
   704  		return outp, err
   705  	}, 90*time.Second); err != nil {
   706  		return
   707  	}
   708  }
   709  
   710  func TestRunNewWithGit(t *testing.T) {
   711  	TrySuite(t, testRunNewWithGit, retryCount)
   712  }
   713  
   714  func testRunNewWithGit(t *T) {
   715  	defer func() {
   716  		os.RemoveAll("/tmp/new-with-git")
   717  	}()
   718  	t.Parallel()
   719  	serv := NewServer(t, WithLogin())
   720  	defer serv.Close()
   721  	if err := serv.Run(); err != nil {
   722  		return
   723  	}
   724  
   725  	cmd := serv.Command()
   726  	cmd.Dir = "/tmp"
   727  
   728  	outp, err := cmd.Exec("new", "new-with-git")
   729  	if err != nil {
   730  		t.Fatal(string(outp))
   731  		return
   732  	}
   733  	makeProt := exec.Command("make", "proto")
   734  	makeProt.Dir = "/tmp/new-with-git"
   735  
   736  	outp, err = makeProt.CombinedOutput()
   737  	if err != nil {
   738  		t.Fatal(string(outp))
   739  		return
   740  	}
   741  
   742  	// for tests, update the micro import to use the current version of the code.
   743  	fname := fmt.Sprintf(makeProt.Dir + "/go.mod")
   744  	f, err := os.OpenFile(fname, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
   745  	if err != nil {
   746  		t.Fatal(string(outp))
   747  		return
   748  	}
   749  	if _, err := f.WriteString("\nreplace github.com/tickoalcantara12/micro/v3 => github.com/tickoalcantara12/micro/v3 master"); err != nil {
   750  		t.Fatal(string(outp))
   751  		return
   752  	}
   753  	// This should point to master, but GOPROXY is not on in the runtime. Remove later.
   754  	if _, err := f.WriteString("\nreplace github.com/micro/go-micro/v3 => github.com/micro/go-micro/v3 v3.0.0-beta.2.0.20200922112322-927d4f8eced6"); err != nil {
   755  		t.Fatal(string(outp))
   756  		return
   757  	}
   758  	f.Close()
   759  
   760  	gitInit := exec.Command("git", "init")
   761  	gitInit.Dir = "/tmp/new-with-git"
   762  	outp, err = gitInit.CombinedOutput()
   763  	if err != nil {
   764  		t.Fatal(string(outp))
   765  	}
   766  
   767  	cmd = serv.Command()
   768  	cmd.Dir = "/tmp/new-with-git"
   769  	outp, err = cmd.Exec("run", ".")
   770  	if err != nil {
   771  		t.Fatal(outp)
   772  	}
   773  
   774  	if err := Try("Find example", t, func() ([]byte, error) {
   775  		outp, err := cmd.Exec("status")
   776  		outp1, _ := cmd.Exec("logs", "new-with-git")
   777  		outp = append(outp, outp1...)
   778  		if err != nil {
   779  			return outp, err
   780  		}
   781  
   782  		// The started service should have the runtime name of "service/example",
   783  		// as the runtime name is the relative path inside a repo.
   784  		if !statusRunning("new-with-git", "latest", outp) {
   785  			return outp, errors.New("Can't find example service in runtime")
   786  		}
   787  		return outp, err
   788  	}, 15*time.Second); err != nil {
   789  		return
   790  	}
   791  
   792  	if err := Try("Find example in list", t, func() ([]byte, error) {
   793  		outp, err := cmd.Exec("services")
   794  		outp1, _ := cmd.Exec("logs", "new-with-git")
   795  		outp = append(outp, outp1...)
   796  		if err != nil {
   797  			return outp, err
   798  		}
   799  		if !strings.Contains(string(outp), "new-with-git") {
   800  			return outp, errors.New("Can't find example service in list")
   801  		}
   802  		return outp, err
   803  	}, 90*time.Second); err != nil {
   804  		return
   805  	}
   806  }
   807  
   808  func TestExistingLogs(t *testing.T) {
   809  	TrySuite(t, testExistingLogs, retryCount)
   810  }
   811  
   812  func testExistingLogs(t *T) {
   813  	t.Parallel()
   814  	serv := NewServer(t, WithLogin())
   815  	defer serv.Close()
   816  	if err := serv.Run(); err != nil {
   817  		return
   818  	}
   819  
   820  	cmd := serv.Command()
   821  
   822  	outp, err := cmd.Exec("run", "./services/test/logger")
   823  	if err != nil {
   824  		t.Fatalf("micro run failure, output: %v", string(outp))
   825  		return
   826  	}
   827  
   828  	if err := Try("logger logs", t, func() ([]byte, error) {
   829  		outp, err = cmd.Exec("logs", "logger")
   830  		if err != nil {
   831  			return outp, err
   832  		}
   833  
   834  		if !strings.Contains(string(outp), "Listening on") || !strings.Contains(string(outp), "This is a log line") {
   835  			return outp, errors.New("Output does not contain expected")
   836  		}
   837  		return outp, nil
   838  	}, 90*time.Second); err != nil {
   839  		return
   840  	}
   841  }
   842  
   843  func TestBranchCheckout(t *testing.T) {
   844  	TrySuite(t, testBranchCheckout, retryCount)
   845  }
   846  
   847  func testBranchCheckout(t *T) {
   848  	t.Parallel()
   849  	serv := NewServer(t, WithLogin())
   850  	defer serv.Close()
   851  	if err := serv.Run(); err != nil {
   852  		return
   853  	}
   854  
   855  	cmd := serv.Command()
   856  
   857  	outp, err := cmd.Exec("run", "./services/test/logger")
   858  	if err != nil {
   859  		t.Fatalf("micro run failure, output: %v", string(outp))
   860  		return
   861  	}
   862  
   863  	if err := Try("logger logs", t, func() ([]byte, error) {
   864  		outp, err = cmd.Exec("logs", "logger")
   865  		if err != nil {
   866  			return outp, err
   867  		}
   868  
   869  		// The log that this branch outputs is different from master, that's what we look for
   870  		if !strings.Contains(string(outp), "Listening on") {
   871  			return outp, errors.New("Output does not contain expected")
   872  		}
   873  		return outp, nil
   874  	}, 60*time.Second); err != nil {
   875  		return
   876  	}
   877  }
   878  
   879  func TestStreamLogsAndThirdPartyRepo(t *testing.T) {
   880  	TrySuite(t, testStreamLogsAndThirdPartyRepo, retryCount)
   881  }
   882  
   883  func testStreamLogsAndThirdPartyRepo(t *T) {
   884  	t.Parallel()
   885  	serv := NewServer(t, WithLogin())
   886  	defer serv.Close()
   887  	if err := serv.Run(); err != nil {
   888  		return
   889  	}
   890  
   891  	cmd := serv.Command()
   892  
   893  	outp, err := cmd.Exec("run", "./services/test/logger")
   894  	if err != nil {
   895  		t.Fatalf("micro run failure, output: %v", string(outp))
   896  		return
   897  	}
   898  
   899  	if err := Try("logger logs", t, func() ([]byte, error) {
   900  		outp, err = cmd.Exec("logs", "logger")
   901  		if err != nil {
   902  			return outp, err
   903  		}
   904  
   905  		if !strings.Contains(string(outp), "Listening on") || !strings.Contains(string(outp), "This is a log line") {
   906  			return outp, errors.New("Output does not contain expected")
   907  		}
   908  		return outp, nil
   909  	}, 90*time.Second); err != nil {
   910  		return
   911  	}
   912  
   913  	cmd.Start("logs", "-n", "1", "-f", "logger")
   914  
   915  	time.Sleep(7 * time.Second)
   916  
   917  	go func() {
   918  		outp, err := cmd.Output()
   919  		if err != nil {
   920  			t.Log(err)
   921  		}
   922  		if len(outp) == 0 {
   923  			t.Fatal("No log lines streamed")
   924  			return
   925  		}
   926  		if !strings.Contains(string(outp), "This is a log line") {
   927  			t.Fatalf("Unexpected logs: %v", string(outp))
   928  			return
   929  		}
   930  		// Logspammer logs every 2 seconds, so we need 2 different
   931  		now := time.Now()
   932  		// leaving the hour here to fix a docker issue
   933  		// when the containers clock is a few hours behind
   934  		stampA := now.Add(-2 * time.Second).Format("04:05")
   935  		stampB := now.Add(-1 * time.Second).Format("04:05")
   936  		if !strings.Contains(string(outp), stampA) && !strings.Contains(string(outp), stampB) {
   937  			t.Fatalf("Timestamp %v or %v not found in logs: %v", stampA, stampB, string(outp))
   938  			return
   939  		}
   940  	}()
   941  
   942  	time.Sleep(7 * time.Second)
   943  
   944  	if err := cmd.Stop(); err != nil {
   945  		t.Fatal(err)
   946  		return
   947  	}
   948  
   949  	time.Sleep(2 * time.Second)
   950  }
   951  
   952  func replaceStringInFile(t *T, filepath string, original, newone string) {
   953  	input, err := ioutil.ReadFile(filepath)
   954  	if err != nil {
   955  		t.Fatal(err)
   956  		return
   957  	}
   958  
   959  	output := strings.ReplaceAll(string(input), original, newone)
   960  	err = ioutil.WriteFile(filepath, []byte(output), 0644)
   961  	if err != nil {
   962  		t.Fatal(err)
   963  		return
   964  	}
   965  }
   966  
   967  func TestParentDependency(t *testing.T) {
   968  	TrySuite(t, testParentDependency, retryCount)
   969  }
   970  
   971  func testParentDependency(t *T) {
   972  	t.Parallel()
   973  	serv := NewServer(t, WithLogin())
   974  	defer serv.Close()
   975  	if err := serv.Run(); err != nil {
   976  		return
   977  	}
   978  
   979  	cmd := serv.Command()
   980  
   981  	outp, err := cmd.Exec("run", "./dep-test/dep-test-service")
   982  	if err != nil {
   983  		t.Fatalf("micro run failure, output: %v", string(outp))
   984  		return
   985  	}
   986  
   987  	if err := Try("Find dep-test-service", t, func() ([]byte, error) {
   988  		outp, err := cmd.Exec("status")
   989  		if err != nil {
   990  			return outp, err
   991  		}
   992  
   993  		if !statusRunning("dep-test-service", "latest", outp) {
   994  			return outp, errors.New("Output should contain dep-test-service")
   995  		}
   996  		return outp, nil
   997  	}, 30*time.Second); err != nil {
   998  		return
   999  	}
  1000  }
  1001  
  1002  func TestRunPrivateSource(t *testing.T) {
  1003  	TrySuite(t, testRunPrivateSource, retryCount)
  1004  }
  1005  
  1006  func testRunPrivateSource(t *T) {
  1007  	t.Parallel()
  1008  	serv := NewServer(t, WithLogin())
  1009  	defer serv.Close()
  1010  	if err := serv.Run(); err != nil {
  1011  		return
  1012  	}
  1013  
  1014  	cmd := serv.Command()
  1015  
  1016  	// get the git credentials, injected by the k8s integration test
  1017  	pat := os.Getenv("GITHUB_PAT")
  1018  	if len(pat) == 0 {
  1019  		t.Logf("Skipping test, missing GITHUB_PAT")
  1020  		return
  1021  	}
  1022  
  1023  	// set the pat in the users config
  1024  	if outp, err := cmd.Exec("user", "config", "set", "git.credentials.github", pat); err != nil {
  1025  		t.Fatalf("Expected no error, got %v %v", err, string(outp))
  1026  		return
  1027  	}
  1028  
  1029  	// run the service
  1030  	if outp, err := cmd.Exec("run", "--image", "localhost:5000/cells:v3", "github.com/micro/test/helloworld"); err != nil {
  1031  		t.Fatalf("Expected no run error, got %v %v", err, string(outp))
  1032  		return
  1033  	}
  1034  
  1035  	if err := Try("Find helloworld in runtime", t, func() ([]byte, error) {
  1036  		outp, err := cmd.Exec("status")
  1037  		if err != nil {
  1038  			return outp, err
  1039  		}
  1040  
  1041  		if !statusRunning("helloworld", "latest", outp) {
  1042  			return outp, errors.New("Can't find helloworld service in runtime")
  1043  		}
  1044  		return outp, err
  1045  	}, 60*time.Second); err != nil {
  1046  		return
  1047  	}
  1048  
  1049  	if err := Try("Find helloworld in registry", t, func() ([]byte, error) {
  1050  		outp, err := cmd.Exec("services")
  1051  		if err != nil {
  1052  			return outp, err
  1053  		}
  1054  		if !strings.Contains(string(outp), "helloworld") {
  1055  			return outp, errors.New("Does not contain helloworld")
  1056  		}
  1057  		return outp, err
  1058  	}, 90*time.Second); err != nil {
  1059  		outp, _ := cmd.Exec("logs", "helloworld")
  1060  		t.Logf("logs %s", string(outp))
  1061  		return
  1062  	}
  1063  
  1064  	// call the service
  1065  	if err := Try("Calling helloworld", t, func() ([]byte, error) {
  1066  		return cmd.Exec("helloworld", "--name=John")
  1067  	}, 30*time.Second); err != nil {
  1068  		return
  1069  	}
  1070  }
  1071  
  1072  func TestRunCustomCredentials(t *testing.T) {
  1073  	TrySuite(t, testRunCustomCredentials, retryCount)
  1074  }
  1075  
  1076  func testRunCustomCredentials(t *T) {
  1077  	t.Parallel()
  1078  	serv := NewServer(t, WithLogin())
  1079  	defer serv.Close()
  1080  	if err := serv.Run(); err != nil {
  1081  		return
  1082  	}
  1083  
  1084  	cmd := serv.Command()
  1085  
  1086  	// get the git credentials, injected by the k8s integration test
  1087  	pat := os.Getenv("GITHUB_PAT")
  1088  	if len(pat) == 0 {
  1089  		t.Logf("Skipping test, missing GITHUB_PAT")
  1090  		return
  1091  	}
  1092  
  1093  	// set the pat in the users config
  1094  	if outp, err := cmd.Exec("user", "config", "set", "git.credentials.url", "github.com"); err != nil {
  1095  		t.Fatalf("Expected no error, got %v %v", err, string(outp))
  1096  		return
  1097  	}
  1098  
  1099  	if outp, err := cmd.Exec("user", "config", "set", "git.credentials.token", pat); err != nil {
  1100  		t.Fatalf("Expected no error, got %v %v", err, string(outp))
  1101  		return
  1102  	}
  1103  
  1104  	// run the service
  1105  	if outp, err := cmd.Exec("run", "--image", "localhost:5000/cells:v3", "github.com/micro/test/helloworld"+branch); err != nil {
  1106  		t.Fatalf("Expected no run error, got %v %v", err, string(outp))
  1107  		return
  1108  	}
  1109  
  1110  	if err := Try("Find micro/test/helloworld in runtime", t, func() ([]byte, error) {
  1111  		outp, err := cmd.Exec("status")
  1112  		if err != nil {
  1113  			return outp, err
  1114  		}
  1115  
  1116  		if !statusRunning("helloworld", version, outp) {
  1117  			return outp, errors.New("Can't find helloworld service in runtime")
  1118  		}
  1119  		return outp, err
  1120  	}, 60*time.Second); err != nil {
  1121  		return
  1122  	}
  1123  
  1124  	if err := Try("Find helloworld in registry", t, func() ([]byte, error) {
  1125  		outp, err := cmd.Exec("services")
  1126  		if err != nil {
  1127  			return outp, err
  1128  		}
  1129  		if !strings.Contains(string(outp), "helloworld") {
  1130  			return outp, errors.New("Does not contain helloworld")
  1131  		}
  1132  		return outp, err
  1133  	}, 300*time.Second); err != nil {
  1134  		outp, _ := cmd.Exec("logs", "helloworld")
  1135  		t.Logf("logs %s", string(outp))
  1136  		return
  1137  	}
  1138  
  1139  	// call the service
  1140  	if err := Try("Calling helloworld", t, func() ([]byte, error) {
  1141  		return cmd.Exec("helloworld", "--name=John")
  1142  	}, 30*time.Second); err != nil {
  1143  		return
  1144  	}
  1145  }
  1146  
  1147  func TestGitSourceUpdateByShortName(t *testing.T) {
  1148  	TrySuite(t, testGitSourceUpdateByShortName, retryCount)
  1149  }
  1150  
  1151  func testGitSourceUpdateByShortName(t *T) {
  1152  	t.Parallel()
  1153  	serv := NewServer(t, WithLogin())
  1154  	defer serv.Close()
  1155  	if err := serv.Run(); err != nil {
  1156  		return
  1157  	}
  1158  
  1159  	cmd := serv.Command()
  1160  
  1161  	// run the service
  1162  	if outp, err := cmd.Exec("run", "github.com/m3o/services/invite"); err != nil {
  1163  		t.Fatalf("Expected no error, got %v %v", err, string(outp))
  1164  		return
  1165  	}
  1166  
  1167  	if err := Try("Find invite in runtime", t, func() ([]byte, error) {
  1168  		outp, err := cmd.Exec("status")
  1169  		if err != nil {
  1170  			return outp, err
  1171  		}
  1172  
  1173  		if !statusRunning("invite", version, outp) {
  1174  			return outp, errors.New("Can't find subfolder-test service in runtime")
  1175  		}
  1176  		return outp, err
  1177  	}, 60*time.Second); err != nil {
  1178  		return
  1179  	}
  1180  
  1181  	if err := Try("Find invite in registry", t, func() ([]byte, error) {
  1182  		outp, err := cmd.Exec("services")
  1183  		if err != nil {
  1184  			return outp, err
  1185  		}
  1186  		if !strings.Contains(string(outp), "invite") {
  1187  			return outp, errors.New("Does not contain invite")
  1188  		}
  1189  		return outp, err
  1190  	}, 300*time.Second); err != nil {
  1191  		outp, _ := cmd.Exec("logs", "invite")
  1192  		t.Log(string(outp))
  1193  		return
  1194  	}
  1195  
  1196  	// call the service
  1197  	if err := Try("Calling invite", t, func() ([]byte, error) {
  1198  		outp, _ := cmd.Exec("logs", "-n=1000", "invite")
  1199  		outp1, err := cmd.Exec("invite", "--help")
  1200  
  1201  		return append(outp1, outp...), err
  1202  	}, 70*time.Second); err != nil {
  1203  		return
  1204  	}
  1205  
  1206  	// update service
  1207  
  1208  	// run the service
  1209  	if outp, err := cmd.Exec("update", "invite"+branch); err != nil {
  1210  		t.Fatalf("Expected no error, got %v %v", err, string(outp))
  1211  		return
  1212  	}
  1213  
  1214  	// look for disconnect
  1215  	if err := Try("Find invite disconnect proof in logs", t, func() ([]byte, error) {
  1216  		outp, err := cmd.Exec("logs", "invite")
  1217  		if err != nil {
  1218  			return outp, err
  1219  		}
  1220  		if !strings.Contains(string(outp), "Disconnect") {
  1221  			return outp, errors.New("Does not contain Disconnect")
  1222  		}
  1223  		return outp, err
  1224  	}, 40*time.Second); err != nil {
  1225  		outp, _ := cmd.Exec("logs", "invite")
  1226  		t.Log(string(outp))
  1227  		return
  1228  	}
  1229  
  1230  	if err := Try("Find invite in runtime", t, func() ([]byte, error) {
  1231  		outp, err := cmd.Exec("status")
  1232  		if err != nil {
  1233  			return outp, err
  1234  		}
  1235  
  1236  		if !statusRunning("invite", version, outp) {
  1237  			return outp, errors.New("Can't find invite service in runtime")
  1238  		}
  1239  		return outp, err
  1240  	}, 60*time.Second); err != nil {
  1241  		return
  1242  	}
  1243  
  1244  	if err := Try("Find invite in registry", t, func() ([]byte, error) {
  1245  		outp, err := cmd.Exec("services")
  1246  		if err != nil {
  1247  			return outp, err
  1248  		}
  1249  		if !strings.Contains(string(outp), "invite") {
  1250  			return outp, errors.New("Does not contain example")
  1251  		}
  1252  		return outp, err
  1253  	}, 300*time.Second); err != nil {
  1254  		outp, _ := cmd.Exec("logs", "invite")
  1255  		t.Log(string(outp))
  1256  		return
  1257  	}
  1258  
  1259  	// call the service
  1260  	if err := Try("Calling invite", t, func() ([]byte, error) {
  1261  		outp, _ := cmd.Exec("logs", "-n=1000", "invite")
  1262  		outp1, err := cmd.Exec("invite", "--help")
  1263  
  1264  		return append(outp1, outp...), err
  1265  	}, 70*time.Second); err != nil {
  1266  		return
  1267  	}
  1268  }
  1269  
  1270  func TestRunPrivateGitlabSource(t *testing.T) {
  1271  	TrySuite(t, testRunPrivateGitlabSource, retryCount)
  1272  }
  1273  
  1274  func testRunPrivateGitlabSource(t *T) {
  1275  	t.Parallel()
  1276  	serv := NewServer(t, WithLogin())
  1277  	defer serv.Close()
  1278  	if err := serv.Run(); err != nil {
  1279  		return
  1280  	}
  1281  
  1282  	cmd := serv.Command()
  1283  
  1284  	// get the git credentials, injected by the k8s integration test
  1285  	pat := os.Getenv("GITLAB_PAT")
  1286  	if len(pat) == 0 {
  1287  		t.Logf("Skipping test, missing GITLAB_PAT")
  1288  		return
  1289  	}
  1290  
  1291  	// set the pat in the users config
  1292  	if outp, err := cmd.Exec("user", "config", "set", "git.credentials.gitlab", pat); err != nil {
  1293  		t.Fatalf("Expected no error, got %v %v", err, string(outp))
  1294  		return
  1295  	}
  1296  
  1297  	// run the service
  1298  	if outp, err := cmd.Exec("run", "--image", "localhost:5000/cells:v3", "gitlab.com/micro-test/private-monorepo-test/subfolder-test"); err != nil {
  1299  		t.Fatalf("Expected no error, got %v %v", err, string(outp))
  1300  		return
  1301  	}
  1302  
  1303  	if err := Try("Find subfolder-test in runtime", t, func() ([]byte, error) {
  1304  		outp, err := cmd.Exec("status")
  1305  		if err != nil {
  1306  			return outp, err
  1307  		}
  1308  
  1309  		if !statusRunning("subfolder-test", version, outp) {
  1310  			return outp, errors.New("Can't find subfolder-test service in runtime")
  1311  		}
  1312  		return outp, err
  1313  	}, 60*time.Second); err != nil {
  1314  		return
  1315  	}
  1316  
  1317  	if err := Try("Find example in registry", t, func() ([]byte, error) {
  1318  		outp, err := cmd.Exec("services")
  1319  		if err != nil {
  1320  			return outp, err
  1321  		}
  1322  		if !strings.Contains(string(outp), "example") {
  1323  			return outp, errors.New("Does not contain example")
  1324  		}
  1325  		return outp, err
  1326  	}, 300*time.Second); err != nil {
  1327  		outp, _ := cmd.Exec("logs", "subfolder-test")
  1328  		t.Log(string(outp))
  1329  		return
  1330  	}
  1331  }
  1332  
  1333  func TestRunPrivateGenericRemote(t *testing.T) {
  1334  	TrySuite(t, testRunPrivateGenericRemote, retryCount)
  1335  }
  1336  
  1337  func testRunPrivateGenericRemote(t *T) {
  1338  	t.Parallel()
  1339  	serv := NewServer(t, WithLogin())
  1340  	defer serv.Close()
  1341  	if err := serv.Run(); err != nil {
  1342  		return
  1343  	}
  1344  
  1345  	cmd := serv.Command()
  1346  
  1347  	// get the git credentials, injected by the k8s integration test
  1348  	pat := os.Getenv("BITBUCKET_PAT")
  1349  	if len(pat) == 0 {
  1350  		t.Logf("Skipping test, missing BITBUCKET_PAT")
  1351  		return
  1352  	}
  1353  
  1354  	// set the pat in the users config
  1355  	if outp, err := cmd.Exec("user", "config", "set", "git.credentials.bitbucket", pat); err != nil {
  1356  		t.Fatalf("Expected no error, got %v %v", err, string(outp))
  1357  		return
  1358  	}
  1359  
  1360  	// run the service
  1361  	if outp, err := cmd.Exec("run", "--image", "localhost:5000/cells:v3", "bitbucket.org/micro-test/private-monorepo-test/subfolder-test"); err != nil {
  1362  		t.Fatalf("Expected no error, got %v %v", err, string(outp))
  1363  		return
  1364  	}
  1365  
  1366  	if err := Try("Find micro/test/helloworld in runtime", t, func() ([]byte, error) {
  1367  		outp, err := cmd.Exec("status")
  1368  		if err != nil {
  1369  			return outp, err
  1370  		}
  1371  
  1372  		if !statusRunning("subfolder-test", version, outp) {
  1373  			return outp, errors.New("Can't find helloworld service in runtime")
  1374  		}
  1375  		return outp, err
  1376  	}, 60*time.Second); err != nil {
  1377  		return
  1378  	}
  1379  
  1380  	if err := Try("Find helloworld in registry", t, func() ([]byte, error) {
  1381  		outp, err := cmd.Exec("services")
  1382  		if err != nil {
  1383  			return outp, err
  1384  		}
  1385  		if !strings.Contains(string(outp), "example") {
  1386  			return outp, errors.New("Does not contain example")
  1387  		}
  1388  		return outp, err
  1389  	}, 300*time.Second); err != nil {
  1390  		outp, _ := cmd.Exec("logs", "subfolder-test")
  1391  		t.Log(string(outp))
  1392  		return
  1393  	}
  1394  
  1395  	// call the service
  1396  	if err := Try("Calling example", t, func() ([]byte, error) {
  1397  		return cmd.Exec("example", "--name=John")
  1398  	}, 30*time.Second); err != nil {
  1399  		return
  1400  	}
  1401  
  1402  	// update service
  1403  
  1404  	// run the service
  1405  	if outp, err := cmd.Exec("run", "--image", "localhost:5000/cells:v3", "gitlab.com/micro-test/private-monorepo-test/subfolder-test"+branch); err != nil {
  1406  		t.Fatalf("Expected no error, got %v %v", err, string(outp))
  1407  		return
  1408  	}
  1409  
  1410  	// We need a better way of knowing the server restarted than a sleep...
  1411  	time.Sleep(5 * time.Second)
  1412  
  1413  	if err := Try("Find micro/test/helloworld in runtime", t, func() ([]byte, error) {
  1414  		outp, err := cmd.Exec("status")
  1415  		if err != nil {
  1416  			return outp, err
  1417  		}
  1418  
  1419  		if !statusRunning("subfolder-test", version, outp) {
  1420  			return outp, errors.New("Can't find helloworld service in runtime")
  1421  		}
  1422  		return outp, err
  1423  	}, 60*time.Second); err != nil {
  1424  		return
  1425  	}
  1426  
  1427  	if err := Try("Find helloworld in registry", t, func() ([]byte, error) {
  1428  		outp, err := cmd.Exec("services")
  1429  		if err != nil {
  1430  			return outp, err
  1431  		}
  1432  		if !strings.Contains(string(outp), "example") {
  1433  			return outp, errors.New("Does not contain example")
  1434  		}
  1435  		return outp, err
  1436  	}, 300*time.Second); err != nil {
  1437  		outp, _ := cmd.Exec("logs", "subfolder-test")
  1438  		t.Log(string(outp))
  1439  		return
  1440  	}
  1441  
  1442  	// call the service
  1443  	if err := Try("Calling example", t, func() ([]byte, error) {
  1444  		return cmd.Exec("example", "--name=John")
  1445  	}, 30*time.Second); err != nil {
  1446  		return
  1447  	}
  1448  }
  1449  
  1450  func TestIdiomaticFolderStructure(t *testing.T) {
  1451  	TrySuite(t, testIdiomaticFolderStructure, retryCount)
  1452  }
  1453  
  1454  func testIdiomaticFolderStructure(t *T) {
  1455  	t.Parallel()
  1456  	serv := NewServer(t, WithLogin())
  1457  	defer serv.Close()
  1458  	if err := serv.Run(); err != nil {
  1459  		return
  1460  	}
  1461  
  1462  	cmd := serv.Command()
  1463  	src := "./services/test/template"
  1464  	if outp, err := cmd.Exec("run", "--image", "localhost:5000/cells:v3", src); err != nil {
  1465  		t.Fatalf("Error running service: %v, %v", err, string(outp))
  1466  		return
  1467  	}
  1468  
  1469  	if err := Try("Find template service in the registry", t, func() ([]byte, error) {
  1470  		outp, err := cmd.Exec("status")
  1471  		outp1, _ := cmd.Exec("logs", "template")
  1472  		if err != nil {
  1473  			return append(outp, outp1...), err
  1474  		}
  1475  
  1476  		// The started service should have the runtime name of "service/example",
  1477  		// as the runtime name is the relative path inside a repo.
  1478  		if !statusRunning("template", "latest", outp) {
  1479  			return outp, errors.New("Can't find template service in runtime")
  1480  		}
  1481  		return outp, err
  1482  	}, 120*time.Second); err != nil {
  1483  		return
  1484  	}
  1485  }