github.com/StackPointCloud/packer@v0.10.2-0.20180716202532-b28098e0f79b/helper/multistep/debug_runner_test.go (about)

     1  package multistep
     2  
     3  import (
     4  	"os"
     5  	"reflect"
     6  	"testing"
     7  	"time"
     8  )
     9  
    10  func TestDebugRunner_Impl(t *testing.T) {
    11  	var raw interface{}
    12  	raw = &DebugRunner{}
    13  	if _, ok := raw.(Runner); !ok {
    14  		t.Fatal("DebugRunner must be a runner.")
    15  	}
    16  }
    17  
    18  func TestDebugRunner_Run(t *testing.T) {
    19  	data := new(BasicStateBag)
    20  	stepA := &TestStepAcc{Data: "a"}
    21  	stepB := &TestStepAcc{Data: "b"}
    22  
    23  	pauseFn := func(loc DebugLocation, name string, state StateBag) {
    24  		key := "data"
    25  		if loc == DebugLocationBeforeCleanup {
    26  			key = "cleanup"
    27  		}
    28  
    29  		if _, ok := state.GetOk(key); !ok {
    30  			state.Put(key, make([]string, 0, 5))
    31  		}
    32  
    33  		data := state.Get(key).([]string)
    34  		state.Put(key, append(data, name))
    35  	}
    36  
    37  	r := &DebugRunner{
    38  		Steps:   []Step{stepA, stepB},
    39  		PauseFn: pauseFn,
    40  	}
    41  
    42  	r.Run(data)
    43  
    44  	// Test data
    45  	expected := []string{"a", "TestStepAcc", "b", "TestStepAcc"}
    46  	results := data.Get("data").([]string)
    47  	if !reflect.DeepEqual(results, expected) {
    48  		t.Errorf("unexpected results: %#v", results)
    49  	}
    50  
    51  	// Test cleanup
    52  	expected = []string{"TestStepAcc", "b", "TestStepAcc", "a"}
    53  	results = data.Get("cleanup").([]string)
    54  	if !reflect.DeepEqual(results, expected) {
    55  		t.Errorf("unexpected results: %#v", results)
    56  	}
    57  }
    58  
    59  // confirm that can't run twice
    60  func TestDebugRunner_Run_Run(t *testing.T) {
    61  	defer func() {
    62  		recover()
    63  	}()
    64  	ch := make(chan chan bool)
    65  	stepInt := &TestStepSync{ch}
    66  	stepWait := &TestStepWaitForever{}
    67  	r := &DebugRunner{Steps: []Step{stepInt, stepWait}}
    68  
    69  	go r.Run(new(BasicStateBag))
    70  	// wait until really running
    71  	<-ch
    72  
    73  	// now try to run aain
    74  	r.Run(new(BasicStateBag))
    75  
    76  	// should not get here in nominal codepath
    77  	t.Errorf("Was able to run an already running DebugRunner")
    78  }
    79  
    80  func TestDebugRunner_Cancel(t *testing.T) {
    81  	ch := make(chan chan bool)
    82  	data := new(BasicStateBag)
    83  	stepA := &TestStepAcc{Data: "a"}
    84  	stepB := &TestStepAcc{Data: "b"}
    85  	stepInt := &TestStepSync{ch}
    86  	stepC := &TestStepAcc{Data: "c"}
    87  
    88  	r := &DebugRunner{}
    89  	r.Steps = []Step{stepA, stepB, stepInt, stepC}
    90  
    91  	// cancelling an idle Runner is a no-op
    92  	r.Cancel()
    93  
    94  	go r.Run(data)
    95  
    96  	// Wait until we reach the sync point
    97  	responseCh := <-ch
    98  
    99  	// Cancel then continue chain
   100  	cancelCh := make(chan bool)
   101  	go func() {
   102  		r.Cancel()
   103  		cancelCh <- true
   104  	}()
   105  
   106  	for {
   107  		if _, ok := data.GetOk(StateCancelled); ok {
   108  			responseCh <- true
   109  			break
   110  		}
   111  
   112  		time.Sleep(10 * time.Millisecond)
   113  	}
   114  
   115  	<-cancelCh
   116  
   117  	// Test run data
   118  	expected := []string{"a", "b"}
   119  	results := data.Get("data").([]string)
   120  	if !reflect.DeepEqual(results, expected) {
   121  		t.Errorf("unexpected result: %#v", results)
   122  	}
   123  
   124  	// Test cleanup data
   125  	expected = []string{"b", "a"}
   126  	results = data.Get("cleanup").([]string)
   127  	if !reflect.DeepEqual(results, expected) {
   128  		t.Errorf("unexpected result: %#v", results)
   129  	}
   130  
   131  	// Test that it says it is cancelled
   132  	cancelled := data.Get(StateCancelled).(bool)
   133  	if !cancelled {
   134  		t.Errorf("not cancelled")
   135  	}
   136  }
   137  
   138  func TestDebugPauseDefault(t *testing.T) {
   139  
   140  	// Create a pipe pair so that writes/reads are blocked until we do it
   141  	r, w, err := os.Pipe()
   142  	if err != nil {
   143  		t.Fatalf("err: %s", err)
   144  	}
   145  
   146  	// Set stdin so we can control it
   147  	oldStdin := os.Stdin
   148  	os.Stdin = r
   149  	defer func() { os.Stdin = oldStdin }()
   150  
   151  	// Start pausing
   152  	complete := make(chan bool, 1)
   153  	go func() {
   154  		dr := &DebugRunner{Steps: []Step{
   155  			&TestStepAcc{Data: "a"},
   156  		}}
   157  		dr.Run(new(BasicStateBag))
   158  		complete <- true
   159  	}()
   160  
   161  	select {
   162  	case <-complete:
   163  		t.Fatal("shouldn't have completed")
   164  	case <-time.After(100 * time.Millisecond):
   165  	}
   166  
   167  	w.Write([]byte("\n\n"))
   168  
   169  	select {
   170  	case <-complete:
   171  	case <-time.After(100 * time.Millisecond):
   172  		t.Fatal("didn't complete")
   173  	}
   174  }