github.com/deis/deis@v1.13.5-0.20170519182049-1d9e59fbdbfc/tests/apps_test.go (about)

     1  // +build integration
     2  
     3  package tests
     4  
     5  import (
     6  	"fmt"
     7  	"math/rand"
     8  	"os"
     9  	"strings"
    10  	"testing"
    11  	"time"
    12  
    13  	"github.com/deis/deis/tests/utils"
    14  )
    15  
    16  var (
    17  	appsCreateCmd          = "apps:create {{.AppName}}"
    18  	appsCreateCmdNoRemote  = "apps:create {{.AppName}} --no-remote"
    19  	appsCreateCmdBuildpack = "apps:create {{.AppName}} --buildpack https://example.com"
    20  	appsListCmd            = "apps:list"
    21  	appsRunCmd             = "apps:run echo Hello, 世界"
    22  	appsOpenCmd            = "apps:open --app={{.AppName}}"
    23  	appsLogsCmd            = "apps:logs --app={{.AppName}}"
    24  	appsLogsLimitCmd       = "apps:logs --app={{.AppName}} -n 1"
    25  	appsInfoCmd            = "apps:info --app={{.AppName}}"
    26  	appsDestroyCmd         = "apps:destroy --app={{.AppName}} --confirm={{.AppName}}"
    27  	appsDestroyCmdNoApp    = "apps:destroy --confirm={{.AppName}}"
    28  	appsTransferCmd        = "apps:transfer {{.NewOwner}} --app={{.AppName}}"
    29  )
    30  
    31  func randomString(n int) string {
    32  	// Be sure we've seeded the random number generator, otherwise we could get the same string
    33  	// every time.
    34  	rand.Seed(time.Now().UnixNano())
    35  	var letters = []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")
    36  	b := make([]rune, n)
    37  	for i := range b {
    38  		b[i] = letters[rand.Intn(len(letters))]
    39  	}
    40  	return string(b)
    41  }
    42  
    43  func TestApps(t *testing.T) {
    44  	params := appsSetup(t)
    45  	appsCreateTest(t, params)
    46  	appsListTest(t, params, false)
    47  	appsLogsTest(t, params)
    48  	appsInfoTest(t, params)
    49  	appsRunTest(t, params)
    50  	appsOpenTest(t, params)
    51  	appsDestroyTest(t, params)
    52  	appsListTest(t, params, true)
    53  	appsTransferTest(t, params)
    54  }
    55  
    56  func appsSetup(t *testing.T) *utils.DeisTestConfig {
    57  	cfg := utils.GetGlobalConfig()
    58  	cfg.AppName = "appssample"
    59  	utils.Execute(t, authLoginCmd, cfg, false, "")
    60  	utils.Execute(t, gitCloneCmd, cfg, false, "")
    61  	return cfg
    62  }
    63  
    64  func appsCreateTest(t *testing.T, params *utils.DeisTestConfig) {
    65  	wd, _ := os.Getwd()
    66  	defer os.Chdir(wd)
    67  	if err := utils.Chdir(params.ExampleApp); err != nil {
    68  		t.Fatal(err)
    69  	}
    70  	// TODO: move --buildpack to client unit tests
    71  	utils.Execute(t, appsCreateCmdBuildpack, params, false, "BUILDPACK_URL")
    72  	utils.Execute(t, appsDestroyCmdNoApp, params, false, "")
    73  	utils.Execute(t, appsCreateCmd, params, false, "")
    74  	utils.Execute(t, appsCreateCmd, params, true, "This field must be unique.")
    75  }
    76  
    77  func appsDestroyTest(t *testing.T, params *utils.DeisTestConfig) {
    78  	if err := utils.Chdir(params.ExampleApp); err != nil {
    79  		t.Fatal(err)
    80  	}
    81  	utils.Execute(t, appsDestroyCmd, params, false, "")
    82  	if err := utils.Chdir(".."); err != nil {
    83  		t.Fatal(err)
    84  	}
    85  	if err := utils.Rmdir(params.ExampleApp); err != nil {
    86  		t.Fatal(err)
    87  	}
    88  }
    89  
    90  func appsInfoTest(t *testing.T, params *utils.DeisTestConfig) {
    91  	utils.Execute(t, appsInfoCmd, params, false, "")
    92  }
    93  
    94  func appsListTest(t *testing.T, params *utils.DeisTestConfig, notflag bool) {
    95  	utils.CheckList(t, appsListCmd, params, params.AppName, notflag)
    96  }
    97  
    98  func appsLogsTest(t *testing.T, params *utils.DeisTestConfig) {
    99  	cmd := appsLogsCmd
   100  	// test for application lifecycle logs
   101  	utils.Execute(t, cmd, params, false, "204 NO CONTENT")
   102  	if err := utils.Chdir(params.ExampleApp); err != nil {
   103  		t.Fatal(err)
   104  	}
   105  	utils.Execute(t, gitPushCmd, params, false, "")
   106  	utils.CurlApp(t, *params)
   107  	utils.Execute(t, cmd, params, false, "created initial release")
   108  	utils.Execute(t, cmd, params, false, "listening on 5000...")
   109  
   110  	utils.Execute(t, appsLogsLimitCmd, params, false, "")
   111  
   112  	if err := utils.Chdir(".."); err != nil {
   113  		t.Fatal(err)
   114  	}
   115  }
   116  
   117  func appsOpenTest(t *testing.T, params *utils.DeisTestConfig) {
   118  	utils.CurlApp(t, *params)
   119  	utils.CurlWithFail(t, fmt.Sprintf("http://%s.%s", "this-app-does-not-exist", params.Domain), true, "404 Not Found")
   120  }
   121  
   122  func appsRunTest(t *testing.T, params *utils.DeisTestConfig) {
   123  	cmd := appsRunCmd
   124  	if err := utils.Chdir(params.ExampleApp); err != nil {
   125  		t.Fatal(err)
   126  	}
   127  	utils.CheckList(t, cmd, params, "Hello, 世界", false)
   128  	utils.Execute(t, "apps:run env", params, true, "GIT_SHA")
   129  	// Fleet/systemd unit files have a limit of 2048 characters per line or else one encounters
   130  	// problems parsing the unit.  To verify long log messages are truncated and do not crash
   131  	// logspout (see https://github.com/deis/deis/issues/2046) we must issue a (relatively) short
   132  	// command via `deis apps:run` that produces a LONG, but testable (predictable) log message we
   133  	// can search for in the output of `deis logs`.
   134  	//
   135  	// The strategy for achieving this is to generate 1k random characters, then use that with a
   136  	// command submitted via `deis apps:run` that will echo those 1k bytes 64x (on a single line).
   137  	// Such a message is long enough to crash logspout if handled improperly and ALSO gives us a
   138  	// large, distinct, and predictable string we can search for in the logs to assert success (and
   139  	// assert that the message didn't crash logspout) WITHOUT ever needing to transmit such an
   140  	// egregiously long command via `deis apps:run`.
   141  	largeString := randomString(1024)
   142  	utils.Execute(t, fmt.Sprintf("apps:run \"printf '%s%%.0s' {1..64}\"", largeString), params, false, largeString)
   143  	// To assert the long message didn't crash logspout AND made it to the logger, we will search
   144  	// the logs for a fragment of the long message-- specifically 2x the random string we generated.
   145  	// This will help us ensure the actual log message made it through and not JUST the log message
   146  	// that states the command being execured via `deis apps:run`.  We want to find the former, not
   147  	// the latter because the latter is too short a message to have possibly crashed logspout if
   148  	// mishandled.
   149  	utils.Execute(t, "logs", params, false, strings.Repeat(largeString, 2))
   150  	if err := utils.Chdir(".."); err != nil {
   151  		t.Fatal(err)
   152  	}
   153  	utils.Execute(t, cmd, params, true, "Not found")
   154  }
   155  
   156  func appsTransferTest(t *testing.T, params *utils.DeisTestConfig) {
   157  	user := utils.GetGlobalConfig()
   158  	user.UserName, user.Password = "app-transfer-test", "test"
   159  	user.AppName = "transfer-test"
   160  	user.NewOwner = params.UserName
   161  	utils.Execute(t, authRegisterCmd, user, false, "")
   162  	utils.Execute(t, authLoginCmd, user, false, "")
   163  	utils.Execute(t, appsCreateCmdNoRemote, user, false, "")
   164  	utils.Execute(t, appsTransferCmd, user, false, "")
   165  	utils.Execute(t, appsInfoCmd, user, true, "403 FORBIDDEN")
   166  	utils.Execute(t, authLoginCmd, params, false, "")
   167  	params.AppName = user.AppName
   168  	utils.CheckList(t, appsInfoCmd, params, params.UserName, false)
   169  }