github.com/containers/libpod@v1.9.4-0.20220419124438-4284fd425507/pkg/hooks/hooks_test.go (about) 1 package hooks 2 3 import ( 4 "context" 5 "fmt" 6 "io/ioutil" 7 "os" 8 "path/filepath" 9 "runtime" 10 "testing" 11 12 current "github.com/containers/libpod/pkg/hooks/1.0.0" 13 rspec "github.com/opencontainers/runtime-spec/specs-go" 14 "github.com/stretchr/testify/assert" 15 ) 16 17 // path is the path to an example hook executable. 18 var path string 19 20 func TestGoodNew(t *testing.T) { 21 ctx := context.Background() 22 23 dir, err := ioutil.TempDir("", "hooks-test-") 24 if err != nil { 25 t.Fatal(err) 26 } 27 defer os.RemoveAll(dir) 28 29 for i, name := range []string{ 30 "01-my-hook.json", 31 "01-UPPERCASE.json", 32 "02-another-hook.json", 33 } { 34 jsonPath := filepath.Join(dir, name) 35 var extraStages string 36 if i == 0 { 37 extraStages = ", \"poststart\", \"poststop\"" 38 } 39 err = ioutil.WriteFile(jsonPath, []byte(fmt.Sprintf("{\"version\": \"1.0.0\", \"hook\": {\"path\": \"%s\", \"timeout\": %d}, \"when\": {\"always\": true}, \"stages\": [\"prestart\"%s]}", path, i+1, extraStages)), 0644) 40 if err != nil { 41 t.Fatal(err) 42 } 43 } 44 45 manager, err := New(ctx, []string{dir}, []string{}) 46 if err != nil { 47 t.Fatal(err) 48 } 49 50 config := &rspec.Spec{} 51 extensionStageHooks, err := manager.Hooks(config, map[string]string{}, false) 52 if err != nil { 53 t.Fatal(err) 54 } 55 56 one := 1 57 two := 2 58 three := 3 59 assert.Equal(t, &rspec.Hooks{ 60 Prestart: []rspec.Hook{ 61 { 62 Path: path, 63 Timeout: &one, 64 }, 65 { 66 Path: path, 67 Timeout: &two, 68 }, 69 { 70 Path: path, 71 Timeout: &three, 72 }, 73 }, 74 Poststart: []rspec.Hook{ 75 { 76 Path: path, 77 Timeout: &one, 78 }, 79 }, 80 Poststop: []rspec.Hook{ 81 { 82 Path: path, 83 Timeout: &one, 84 }, 85 }, 86 }, config.Hooks) 87 88 var nilExtensionStageHooks map[string][]rspec.Hook 89 assert.Equal(t, nilExtensionStageHooks, extensionStageHooks) 90 } 91 92 func TestBadNew(t *testing.T) { 93 ctx := context.Background() 94 95 dir, err := ioutil.TempDir("", "hooks-test-") 96 if err != nil { 97 t.Fatal(err) 98 } 99 defer os.RemoveAll(dir) 100 101 jsonPath := filepath.Join(dir, "a.json") 102 err = ioutil.WriteFile(jsonPath, []byte("{\"version\": \"-1\"}"), 0644) 103 if err != nil { 104 t.Fatal(err) 105 } 106 107 _, err = New(ctx, []string{dir}, []string{}) 108 if err == nil { 109 t.Fatal("unexpected success") 110 } 111 assert.Regexp(t, "^parsing hook \"[^\"]*a.json\": unrecognized hook version: \"-1\"$", err.Error()) 112 } 113 114 func TestBrokenMatch(t *testing.T) { 115 manager := Manager{ 116 hooks: map[string]*current.Hook{ 117 "a.json": { 118 Version: current.Version, 119 Hook: rspec.Hook{ 120 Path: "/a/b/c", 121 }, 122 When: current.When{ 123 Commands: []string{"["}, 124 }, 125 Stages: []string{"prestart"}, 126 }, 127 }, 128 } 129 config := &rspec.Spec{ 130 Process: &rspec.Process{ 131 Args: []string{"/bin/sh"}, 132 }, 133 } 134 extensionStageHooks, err := manager.Hooks(config, map[string]string{}, false) 135 if err == nil { 136 t.Fatal("unexpected success") 137 } 138 assert.Regexp(t, "^matching hook \"a\\.json\": command: error parsing regexp: .*", err.Error()) 139 140 var nilExtensionStageHooks map[string][]rspec.Hook 141 assert.Equal(t, nilExtensionStageHooks, extensionStageHooks) 142 } 143 144 func TestInvalidStage(t *testing.T) { 145 always := true 146 manager := Manager{ 147 hooks: map[string]*current.Hook{ 148 "a.json": { 149 Version: current.Version, 150 Hook: rspec.Hook{ 151 Path: "/a/b/c", 152 }, 153 When: current.When{ 154 Always: &always, 155 }, 156 Stages: []string{"does-not-exist"}, 157 }, 158 }, 159 } 160 extensionStageHooks, err := manager.Hooks(&rspec.Spec{}, map[string]string{}, false) 161 if err == nil { 162 t.Fatal("unexpected success") 163 } 164 assert.Regexp(t, "^hook \"a\\.json\": unknown stage \"does-not-exist\"$", err.Error()) 165 166 var nilExtensionStageHooks map[string][]rspec.Hook 167 assert.Equal(t, nilExtensionStageHooks, extensionStageHooks) 168 } 169 170 func TestExtensionStage(t *testing.T) { 171 always := true 172 manager := Manager{ 173 hooks: map[string]*current.Hook{ 174 "a.json": { 175 Version: current.Version, 176 Hook: rspec.Hook{ 177 Path: "/a/b/c", 178 }, 179 When: current.When{ 180 Always: &always, 181 }, 182 Stages: []string{"prestart", "poststop", "a", "b"}, 183 }, 184 }, 185 extensionStages: []string{"poststop", "a", "b", "c"}, 186 } 187 188 config := &rspec.Spec{} 189 extensionStageHooks, err := manager.Hooks(config, map[string]string{}, false) 190 if err != nil { 191 t.Fatal(err) 192 } 193 194 assert.Equal(t, &rspec.Hooks{ 195 Prestart: []rspec.Hook{ 196 { 197 Path: "/a/b/c", 198 }, 199 }, 200 }, config.Hooks) 201 202 assert.Equal(t, map[string][]rspec.Hook{ 203 "poststop": { 204 { 205 Path: "/a/b/c", 206 }, 207 }, 208 "a": { 209 { 210 Path: "/a/b/c", 211 }, 212 }, 213 "b": { 214 { 215 Path: "/a/b/c", 216 }, 217 }, 218 }, extensionStageHooks) 219 } 220 221 func init() { 222 if runtime.GOOS != "windows" { 223 path = "/bin/sh" 224 } else { 225 panic("we need a reliable executable path on Windows") 226 } 227 }