github.com/maxgio92/test-infra@v0.1.0/kubetest/process/process_test.go (about)

     1  /*
     2  Copyright 2017 The Kubernetes Authors.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package process
    18  
    19  import (
    20  	"errors"
    21  	"log"
    22  	"os/exec"
    23  	"strconv"
    24  	"strings"
    25  	"testing"
    26  	"time"
    27  
    28  	"github.com/maxgio92/test-infra/kubetest/util"
    29  )
    30  
    31  func TestXMLWrap(t *testing.T) {
    32  	cases := []struct {
    33  		name            string
    34  		interrupted     bool
    35  		shouldInterrupt bool
    36  		err             string
    37  		expectSkipped   bool
    38  		expectError     bool
    39  	}{
    40  		{
    41  			name: "xmlWrap can pass",
    42  		},
    43  		{
    44  			name:        "xmlWrap can error",
    45  			err:         "hello there",
    46  			expectError: true,
    47  		},
    48  		{
    49  			name:            "xmlWrap always errors on interrupt",
    50  			err:             "",
    51  			shouldInterrupt: true,
    52  			expectError:     true,
    53  		},
    54  		{
    55  			name:            "xmlWrap errors on interrupt",
    56  			shouldInterrupt: true,
    57  			err:             "the step failed",
    58  			expectError:     true,
    59  		},
    60  		{
    61  			name:          "xmlWrap skips errors when already interrupted",
    62  			interrupted:   true,
    63  			err:           "this failed because we interrupted the previous step",
    64  			expectSkipped: true,
    65  		},
    66  		{
    67  			name:        "xmlWrap can pass when interrupted",
    68  			interrupted: true,
    69  			err:         "",
    70  		},
    71  	}
    72  
    73  	for _, tc := range cases {
    74  		interrupt := time.NewTimer(time.Duration(0))
    75  		terminate := time.NewTimer(time.Duration(0))
    76  		c := NewControl(time.Duration(0), interrupt, terminate, false)
    77  		c.interrupted = tc.interrupted
    78  		suite := util.TestSuite{
    79  			Failures: 6,
    80  			Tests:    9,
    81  		}
    82  		err := c.XMLWrap(&suite, tc.name, func() error {
    83  			if tc.shouldInterrupt {
    84  				c.interrupted = true
    85  			}
    86  			if tc.err != "" {
    87  				return errors.New(tc.err)
    88  			}
    89  			return nil
    90  		})
    91  
    92  		if tc.shouldInterrupt && tc.expectError {
    93  			if err == nil {
    94  				t.Fatalf("Case %s did not error", tc.name)
    95  			}
    96  			if tc.err == "" {
    97  				tc.err = err.Error()
    98  			}
    99  		}
   100  		if (tc.err == "") != (err == nil) {
   101  			t.Errorf("Case %s expected err: %s != actual: %v", tc.name, tc.err, err)
   102  		}
   103  		if tc.shouldInterrupt && !c.interrupted {
   104  			t.Errorf("Case %s did not interrupt", tc.name)
   105  		}
   106  		if len(suite.Cases) != 1 {
   107  			t.Fatalf("Case %s did not result in a single suite testcase: %v", tc.name, suite.Cases)
   108  		}
   109  
   110  		sc := suite.Cases[0]
   111  		if sc.Name != tc.name {
   112  			t.Errorf("Case %s resulted in wrong test case name %s", tc.name, sc.Name)
   113  		}
   114  		if tc.expectError {
   115  			if sc.Failure != tc.err {
   116  				t.Errorf("Case %s expected error %s but got %s", tc.name, tc.err, sc.Failure)
   117  			}
   118  			if suite.Failures != 7 {
   119  				t.Errorf("Case %s failed and should increase suite failures from 6 to 7, found: %d", tc.name, suite.Failures)
   120  			}
   121  		} else if tc.expectSkipped {
   122  			if sc.Skipped != tc.err {
   123  				t.Errorf("Case %s expected skipped %s but got %s", tc.name, tc.err, sc.Skipped)
   124  			}
   125  			if suite.Failures != 7 {
   126  				t.Errorf("Case %s interrupted and increase suite failures from 6 to 7, found: %d", tc.name, suite.Failures)
   127  			}
   128  		} else {
   129  			if suite.Failures != 6 {
   130  				t.Errorf("Case %s passed so suite failures should remain at 6, found: %d", tc.name, suite.Failures)
   131  			}
   132  		}
   133  
   134  	}
   135  }
   136  
   137  func TestOutput(t *testing.T) {
   138  	cases := []struct {
   139  		name              string
   140  		terminated        bool
   141  		interrupted       bool
   142  		causeTermination  bool
   143  		causeInterruption bool
   144  		pass              bool
   145  		sleep             int
   146  		output            bool
   147  		shouldError       bool
   148  		shouldInterrupt   bool
   149  		shouldTerminate   bool
   150  	}{
   151  		{
   152  			name: "finishRunning can pass",
   153  			pass: true,
   154  		},
   155  		{
   156  			name:   "output can pass",
   157  			output: true,
   158  			pass:   true,
   159  		},
   160  		{
   161  			name:        "finishRuning can fail",
   162  			pass:        false,
   163  			shouldError: true,
   164  		},
   165  		{
   166  			name:        "output can fail",
   167  			pass:        false,
   168  			output:      true,
   169  			shouldError: true,
   170  		},
   171  		{
   172  			name:        "finishRunning should error when terminated",
   173  			terminated:  true,
   174  			pass:        true,
   175  			shouldError: true,
   176  		},
   177  		{
   178  			name:        "output should error when terminated",
   179  			terminated:  true,
   180  			pass:        true,
   181  			output:      true,
   182  			shouldError: true,
   183  		},
   184  		{
   185  			name:              "finishRunning should interrupt when interrupted",
   186  			pass:              true,
   187  			sleep:             60,
   188  			causeInterruption: true,
   189  			shouldError:       true,
   190  		},
   191  		{
   192  			name:              "output should interrupt when interrupted",
   193  			pass:              true,
   194  			sleep:             60,
   195  			output:            true,
   196  			causeInterruption: true,
   197  			shouldError:       true,
   198  		},
   199  		{
   200  			name:             "output should terminate when terminated",
   201  			pass:             true,
   202  			sleep:            60,
   203  			output:           true,
   204  			causeTermination: true,
   205  			shouldError:      true,
   206  		},
   207  		{
   208  			name:             "finishRunning should terminate when terminated",
   209  			pass:             true,
   210  			sleep:            60,
   211  			causeTermination: true,
   212  			shouldError:      true,
   213  		},
   214  	}
   215  
   216  	clearTimers := func(c *Control) {
   217  		if !c.Terminate.Stop() {
   218  			<-c.Terminate.C
   219  		}
   220  		if !c.Interrupt.Stop() {
   221  			<-c.Interrupt.C
   222  		}
   223  	}
   224  
   225  	for _, tc := range cases {
   226  		log.Println(tc.name)
   227  		interrupt := time.NewTimer(time.Duration(0))
   228  		terminate := time.NewTimer(time.Duration(0))
   229  		c := NewControl(time.Duration(0), interrupt, terminate, false)
   230  		c.terminated = tc.terminated
   231  		c.interrupted = tc.interrupted
   232  		clearTimers(c)
   233  		if tc.causeInterruption {
   234  			interrupt.Reset(0)
   235  		}
   236  		if tc.causeTermination {
   237  			terminate.Reset(0)
   238  		}
   239  		var cmd *exec.Cmd
   240  		if !tc.pass {
   241  			cmd = exec.Command("false")
   242  		} else if tc.sleep == 0 {
   243  			cmd = exec.Command("true")
   244  		} else {
   245  			cmd = exec.Command("sleep", strconv.Itoa(tc.sleep))
   246  		}
   247  		var err error
   248  		if tc.output {
   249  			_, err = c.Output(cmd)
   250  		} else {
   251  			err = c.FinishRunning(cmd)
   252  		}
   253  		if err == nil == tc.shouldError {
   254  			t.Errorf("Step %s shouldError=%v error: %v", tc.name, tc.shouldError, err)
   255  		}
   256  		if tc.causeInterruption && !c.interrupted {
   257  			t.Errorf("Step %s did not interrupt, err: %v", tc.name, err)
   258  		} else if tc.causeInterruption && !terminate.Reset(0) {
   259  			t.Errorf("Step %s did not reset the terminate timer: %v", tc.name, err)
   260  		}
   261  		if tc.causeTermination && !c.terminated {
   262  			t.Errorf("Step %s did not terminate, err: %v", tc.name, err)
   263  		}
   264  	}
   265  }
   266  
   267  func TestFinishRunningParallel(t *testing.T) {
   268  	cases := []struct {
   269  		name              string
   270  		terminated        bool
   271  		interrupted       bool
   272  		causeTermination  bool
   273  		causeInterruption bool
   274  		cmds              []*exec.Cmd
   275  		shouldError       bool
   276  		shouldInterrupt   bool
   277  		shouldTerminate   bool
   278  	}{
   279  		{
   280  			name: "finishRunningParallel with single command can pass",
   281  			cmds: []*exec.Cmd{exec.Command("true")},
   282  		},
   283  		{
   284  			name: "finishRunningParallel with multiple commands can pass",
   285  			cmds: []*exec.Cmd{exec.Command("true"), exec.Command("true")},
   286  		},
   287  		{
   288  			name:        "finishRunningParallel with single command can fail",
   289  			cmds:        []*exec.Cmd{exec.Command("false")},
   290  			shouldError: true,
   291  		},
   292  		{
   293  			name:        "finishRunningParallel with multiple commands can fail",
   294  			cmds:        []*exec.Cmd{exec.Command("true"), exec.Command("false")},
   295  			shouldError: true,
   296  		},
   297  		{
   298  			name:        "finishRunningParallel should error when terminated",
   299  			cmds:        []*exec.Cmd{exec.Command("true"), exec.Command("true")},
   300  			terminated:  true,
   301  			shouldError: true,
   302  		},
   303  		{
   304  			name:              "finishRunningParallel should interrupt when interrupted",
   305  			cmds:              []*exec.Cmd{exec.Command("true"), exec.Command("sleep", "60"), exec.Command("sleep", "30")},
   306  			causeInterruption: true,
   307  			shouldError:       true,
   308  		},
   309  		{
   310  			name:             "finishRunningParallel should terminate when terminated",
   311  			cmds:             []*exec.Cmd{exec.Command("true"), exec.Command("sleep", "60"), exec.Command("sleep", "30")},
   312  			causeTermination: true,
   313  			shouldError:      true,
   314  		},
   315  	}
   316  
   317  	clearTimers := func(c *Control) {
   318  		if !c.Terminate.Stop() {
   319  			<-c.Terminate.C
   320  		}
   321  		if !c.Interrupt.Stop() {
   322  			<-c.Interrupt.C
   323  		}
   324  	}
   325  
   326  	for _, tc := range cases {
   327  		log.Println(tc.name)
   328  		interrupt := time.NewTimer(time.Duration(0))
   329  		terminate := time.NewTimer(time.Duration(0))
   330  		c := NewControl(time.Duration(0), interrupt, terminate, false)
   331  		c.terminated = tc.terminated
   332  		c.interrupted = tc.interrupted
   333  		clearTimers(c)
   334  		if tc.causeInterruption {
   335  			interrupt.Reset(1 * time.Second)
   336  		}
   337  		if tc.causeTermination {
   338  			terminate.Reset(1 * time.Second)
   339  		}
   340  
   341  		err := c.FinishRunningParallel(tc.cmds...)
   342  		if err == nil == tc.shouldError {
   343  			t.Errorf("TC %q shouldError=%v error: %v", tc.name, tc.shouldError, err)
   344  		}
   345  		if tc.causeInterruption && !c.interrupted {
   346  			t.Errorf("TC %q did not interrupt, err: %v", tc.name, err)
   347  		} else if tc.causeInterruption && !terminate.Reset(0) {
   348  			t.Errorf("TC %q did not reset the terminate timer: %v", tc.name, err)
   349  		}
   350  		if tc.causeTermination && !c.terminated {
   351  			t.Errorf("TC %q did not terminate, err: %v", tc.name, err)
   352  		}
   353  	}
   354  }
   355  
   356  func TestOutputOutputs(t *testing.T) {
   357  	interrupt := time.NewTimer(time.Duration(1) * time.Second)
   358  	terminate := time.NewTimer(time.Duration(1) * time.Second)
   359  	c := NewControl(time.Duration(1)*time.Second, interrupt, terminate, false)
   360  
   361  	b, err := c.Output(exec.Command("echo", "hello world"))
   362  	txt := string(b)
   363  	if err != nil {
   364  		t.Fatalf("failed to echo: %v", err)
   365  	}
   366  	if !strings.Contains(txt, "hello world") {
   367  		t.Errorf("output() did not echo hello world: %v", txt)
   368  	}
   369  }