github.com/spinnaker/spin@v1.30.0/cmd/canary/canary-config/retro_test.go (about)

     1  // Copyright (c) 2019, Waze, Inc.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //   http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  //   Unless required by applicable law or agreed to in writing, software
    10  //   distributed under the License is distributed on an "AS IS" BASIS,
    11  //   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  //   See the License for the specific language governing permissions and
    13  //   limitations under the License.
    14  
    15  package canary_config
    16  
    17  import (
    18  	"io/ioutil"
    19  	"net/http"
    20  	"net/http/httptest"
    21  	"os"
    22  	"testing"
    23  	"time"
    24  
    25  	"github.com/spinnaker/spin/cmd"
    26  	"github.com/spinnaker/spin/cmd/canary"
    27  	"github.com/spinnaker/spin/util"
    28  )
    29  
    30  func TestCanaryConfigRetro_file(t *testing.T) {
    31  	ts := gateServerRetroPass()
    32  	defer ts.Close()
    33  
    34  	tempFile := tempCanaryConfigFile(testCanaryConfigJsonStr)
    35  	if tempFile == nil {
    36  		t.Fatal("Could not create temp canary config file.")
    37  	}
    38  	defer os.Remove(tempFile.Name())
    39  
    40  	rootCmd, rootOpts := cmd.NewCmdRoot(ioutil.Discard, ioutil.Discard)
    41  	canaryCmd, canaryOpts := canary.NewCanaryCmd(rootOpts)
    42  	canaryCmd.AddCommand(NewCanaryConfigCmd(canaryOpts))
    43  	rootCmd.AddCommand(canaryCmd)
    44  
    45  	args := []string{
    46  		"canary", "canary-config", "retro",
    47  		"--file", tempFile.Name(),
    48  		"--control-group", "control-v000",
    49  		"--control-location", "us-central1",
    50  		"--experiment-group", "experiment-v000",
    51  		"--experiment-location", "us-central1",
    52  		"--start", "2019-09-17T17:16:02.600Z",
    53  		"--end", "2019-09-17T18:16:02.600Z",
    54  		"--gate-endpoint", ts.URL,
    55  	}
    56  	rootCmd.SetArgs(args)
    57  	err := rootCmd.Execute()
    58  	if err != nil {
    59  		t.Fatalf("Command failed with: %s", err)
    60  	}
    61  }
    62  
    63  func TestCanaryConfigRetro_stdin(t *testing.T) {
    64  	ts := gateServerRetroPass()
    65  	defer ts.Close()
    66  
    67  	tempFile := tempCanaryConfigFile(testCanaryConfigJsonStr)
    68  	if tempFile == nil {
    69  		t.Fatal("Could not create temp canary config file.")
    70  	}
    71  	defer os.Remove(tempFile.Name())
    72  
    73  	// Prepare Stdin for test reading.
    74  	tempFile.Seek(0, 0)
    75  	oldStdin := os.Stdin
    76  	defer func() { os.Stdin = oldStdin }()
    77  	os.Stdin = tempFile
    78  
    79  	rootCmd, rootOpts := cmd.NewCmdRoot(ioutil.Discard, ioutil.Discard)
    80  	canaryCmd, canaryOpts := canary.NewCanaryCmd(rootOpts)
    81  	canaryCmd.AddCommand(NewCanaryConfigCmd(canaryOpts))
    82  	rootCmd.AddCommand(canaryCmd)
    83  
    84  	args := []string{
    85  		"canary", "canary-config", "retro",
    86  		"--control-group", "control-v000",
    87  		"--control-location", "us-central1",
    88  		"--experiment-group", "experiment-v000",
    89  		"--experiment-location", "us-central1",
    90  		"--start", "2019-09-17T17:16:02.600Z",
    91  		"--end", "2019-09-17T18:16:02.600Z",
    92  		"--gate-endpoint", ts.URL,
    93  	}
    94  	rootCmd.SetArgs(args)
    95  	err := rootCmd.Execute()
    96  	if err != nil {
    97  		t.Fatalf("Command failed with: %s", err)
    98  	}
    99  }
   100  
   101  func TestCanaryConfigRetro_fail(t *testing.T) {
   102  	ts := testGateFail()
   103  	defer ts.Close()
   104  
   105  	tempFile := tempCanaryConfigFile(testCanaryConfigJsonStr)
   106  	if tempFile == nil {
   107  		t.Fatal("Could not create temp canary config file.")
   108  	}
   109  	defer os.Remove(tempFile.Name())
   110  
   111  	rootCmd, rootOpts := cmd.NewCmdRoot(ioutil.Discard, ioutil.Discard)
   112  	canaryCmd, canaryOpts := canary.NewCanaryCmd(rootOpts)
   113  	canaryCmd.AddCommand(NewCanaryConfigCmd(canaryOpts))
   114  	rootCmd.AddCommand(canaryCmd)
   115  
   116  	args := []string{
   117  		"canary", "canary-config", "retro",
   118  		"--file", tempFile.Name(),
   119  		"--control-group", "control-v000",
   120  		"--control-location", "us-central1",
   121  		"--experiment-group", "experiment-v000",
   122  		"--experiment-location", "us-central1",
   123  		"--start", "2019-09-17T17:16:02.600Z",
   124  		"--end", "2019-09-17T18:16:02.600Z",
   125  		"--gate-endpoint", ts.URL,
   126  	}
   127  	rootCmd.SetArgs(args)
   128  	err := rootCmd.Execute()
   129  	if err == nil {
   130  		t.Fatalf("Command failed with: %s", err)
   131  	}
   132  }
   133  
   134  func TestCanaryConfigRetro_timeout(t *testing.T) {
   135  	retrySleepCycle = 1 * time.Millisecond
   136  
   137  	ts := gateServerExecHang()
   138  	defer ts.Close()
   139  
   140  	tempFile := tempCanaryConfigFile(testCanaryConfigJsonStr)
   141  	if tempFile == nil {
   142  		t.Fatal("Could not create temp canary config file.")
   143  	}
   144  	defer os.Remove(tempFile.Name())
   145  
   146  	rootCmd, rootOpts := cmd.NewCmdRoot(ioutil.Discard, ioutil.Discard)
   147  	canaryCmd, canaryOpts := canary.NewCanaryCmd(rootOpts)
   148  	canaryCmd.AddCommand(NewCanaryConfigCmd(canaryOpts))
   149  	rootCmd.AddCommand(canaryCmd)
   150  
   151  	args := []string{
   152  		"canary", "canary-config", "retro",
   153  		"--file", tempFile.Name(),
   154  		"--control-group", "control-v000",
   155  		"--control-location", "us-central1",
   156  		"--experiment-group", "experiment-v000",
   157  		"--experiment-location", "us-central1",
   158  		"--start", "2019-09-17T17:16:02.600Z",
   159  		"--end", "2019-09-17T18:16:02.600Z",
   160  		"--gate-endpoint", ts.URL,
   161  	}
   162  	rootCmd.SetArgs(args)
   163  	err := rootCmd.Execute()
   164  	if err == nil {
   165  		t.Fatalf("Command failed with: %s", err)
   166  	}
   167  }
   168  
   169  func gateServerRetroPass() *httptest.Server {
   170  	mux := util.TestGateMuxWithVersionHandler()
   171  	mux.Handle("/v2/canaries/canary", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
   172  		w.Header().Add("content-type", "application/json")
   173  		w.Write([]byte(canaryExecRespJson))
   174  	}))
   175  
   176  	mux.Handle("/v2/canaries/canary/executionId", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
   177  		w.Header().Add("content-type", "application/json")
   178  		w.Write([]byte(canaryFinishedPassJson))
   179  	}))
   180  	return httptest.NewServer(mux)
   181  }
   182  
   183  func gateServerExecHang() *httptest.Server {
   184  	mux := util.TestGateMuxWithVersionHandler()
   185  	mux.Handle("/v2/canaries/canary", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
   186  		w.Header().Add("content-type", "application/json")
   187  		w.Write([]byte(canaryExecRespJson))
   188  	}))
   189  
   190  	mux.Handle("/v2/canaries/canary/executionId", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
   191  		w.Header().Add("content-type", "application/json")
   192  		w.Write([]byte(canaryUnfinishedJson))
   193  	}))
   194  	return httptest.NewServer(mux)
   195  }
   196  
   197  const canaryExecRespJson = `
   198  {
   199    "canaryExecutionId": "executionId"
   200  }
   201  `
   202  
   203  const canaryUnfinishedJson = `
   204  {
   205    "complete": false
   206  }
   207  `
   208  
   209  const canaryFinishedPassJson = `
   210  {
   211    "complete": true,
   212    "result": {
   213      "judgeResult": {
   214        "score": {
   215          "classification": "PASS"
   216        }
   217      }
   218    }
   219  }
   220  `