github.com/hanks177/podman/v4@v4.1.3-0.20220613032544-16d90015bc83/pkg/hooks/1.0.0/when_test.go (about)

     1  package hook
     2  
     3  import (
     4  	"fmt"
     5  	"testing"
     6  
     7  	rspec "github.com/opencontainers/runtime-spec/specs-go"
     8  	"github.com/stretchr/testify/assert"
     9  )
    10  
    11  func TestNoMatch(t *testing.T) {
    12  	config := &rspec.Spec{}
    13  	for _, o := range []bool{true, false} {
    14  		or := o
    15  		t.Run(fmt.Sprintf("or %t", or), func(t *testing.T) {
    16  			when := When{Or: or}
    17  			match, err := when.Match(config, map[string]string{}, false)
    18  			if err != nil {
    19  				t.Fatal(err)
    20  			}
    21  			assert.Equal(t, false, match)
    22  		})
    23  	}
    24  }
    25  
    26  func TestAlways(t *testing.T) {
    27  	config := &rspec.Spec{}
    28  	processStruct := &rspec.Process{
    29  		Args: []string{"/bin/sh", "a", "b"},
    30  	}
    31  	for _, a := range []bool{true, false} {
    32  		always := a
    33  		for _, o := range []bool{true, false} {
    34  			or := o
    35  			for _, p := range []*rspec.Process{processStruct, nil} {
    36  				process := p
    37  				t.Run(fmt.Sprintf("always %t, or %t, has process %t", always, or, process != nil), func(t *testing.T) {
    38  					config.Process = process
    39  					when := When{Always: &always, Or: or}
    40  					match, err := when.Match(config, map[string]string{}, false)
    41  					if err != nil {
    42  						t.Fatal(err)
    43  					}
    44  					assert.Equal(t, always, match)
    45  				})
    46  			}
    47  		}
    48  	}
    49  }
    50  
    51  func TestHasBindMountsAnd(t *testing.T) {
    52  	hasBindMounts := true
    53  	when := When{HasBindMounts: &hasBindMounts}
    54  	config := &rspec.Spec{}
    55  	for _, b := range []bool{false, true} {
    56  		containerHasBindMounts := b
    57  		t.Run(fmt.Sprintf("%t", containerHasBindMounts), func(t *testing.T) {
    58  			match, err := when.Match(config, map[string]string{}, containerHasBindMounts)
    59  			if err != nil {
    60  				t.Fatal(err)
    61  			}
    62  			assert.Equal(t, containerHasBindMounts, match)
    63  		})
    64  	}
    65  }
    66  
    67  func TestHasBindMountsOr(t *testing.T) {
    68  	hasBindMounts := true
    69  	when := When{HasBindMounts: &hasBindMounts, Or: true}
    70  	config := &rspec.Spec{}
    71  	for _, b := range []bool{false, true} {
    72  		containerHasBindMounts := b
    73  		t.Run(fmt.Sprintf("%t", containerHasBindMounts), func(t *testing.T) {
    74  			match, err := when.Match(config, map[string]string{}, containerHasBindMounts)
    75  			if err != nil {
    76  				t.Fatal(err)
    77  			}
    78  			assert.Equal(t, containerHasBindMounts, match)
    79  		})
    80  	}
    81  }
    82  
    83  func TestAnnotations(t *testing.T) {
    84  	when := When{
    85  		Annotations: map[string]string{
    86  			"^a$": "^b$",
    87  			"^c$": "^d$",
    88  		},
    89  	}
    90  	config := &rspec.Spec{}
    91  	for _, tt := range []struct {
    92  		name        string
    93  		annotations map[string]string
    94  		or          bool
    95  		match       bool
    96  	}{
    97  		{
    98  			name: "matching both, and",
    99  			annotations: map[string]string{
   100  				"a": "b",
   101  				"c": "d",
   102  				"e": "f",
   103  			},
   104  			or:    false,
   105  			match: true,
   106  		},
   107  		{
   108  			name: "matching one, and",
   109  			annotations: map[string]string{
   110  				"a": "b",
   111  			},
   112  			or:    false,
   113  			match: false,
   114  		},
   115  		{
   116  			name: "matching one, or",
   117  			annotations: map[string]string{
   118  				"a": "b",
   119  			},
   120  			or:    true,
   121  			match: true,
   122  		},
   123  		{
   124  			name: "key-only, or",
   125  			annotations: map[string]string{
   126  				"a": "bc",
   127  			},
   128  			or:    true,
   129  			match: false,
   130  		},
   131  		{
   132  			name: "value-only, or",
   133  			annotations: map[string]string{
   134  				"ac": "b",
   135  			},
   136  			or:    true,
   137  			match: false,
   138  		},
   139  	} {
   140  		test := tt
   141  		t.Run(test.name, func(t *testing.T) {
   142  			when.Or = test.or
   143  			match, err := when.Match(config, test.annotations, false)
   144  			if err != nil {
   145  				t.Fatal(err)
   146  			}
   147  			assert.Equal(t, test.match, match)
   148  		})
   149  	}
   150  }
   151  
   152  func TestCommands(t *testing.T) {
   153  	when := When{
   154  		Commands: []string{
   155  			"^/bin/sh$",
   156  		},
   157  	}
   158  	config := &rspec.Spec{}
   159  	for _, tt := range []struct {
   160  		name    string
   161  		process *rspec.Process
   162  		match   bool
   163  	}{
   164  		{
   165  			name: "good",
   166  			process: &rspec.Process{
   167  				Args: []string{"/bin/sh", "a", "b"},
   168  			},
   169  			match: true,
   170  		},
   171  		{
   172  			name: "extra characters",
   173  			process: &rspec.Process{
   174  				Args: []string{"/bin/shell", "a", "b"},
   175  			},
   176  			match: false,
   177  		},
   178  		{
   179  			name:  "process unset",
   180  			match: false,
   181  		},
   182  	} {
   183  		test := tt
   184  		t.Run(test.name, func(t *testing.T) {
   185  			config.Process = test.process
   186  			match, err := when.Match(config, map[string]string{}, false)
   187  			if err != nil {
   188  				t.Fatal(err)
   189  			}
   190  			assert.Equal(t, test.match, match)
   191  		})
   192  	}
   193  }
   194  
   195  func TestCommandsEmptyProcessArgs(t *testing.T) {
   196  	when := When{
   197  		Commands: []string{
   198  			"^/bin/sh$",
   199  		},
   200  	}
   201  	config := &rspec.Spec{
   202  		Process: &rspec.Process{},
   203  	}
   204  	_, err := when.Match(config, map[string]string{}, false)
   205  	if err == nil {
   206  		t.Fatal("unexpected success")
   207  	}
   208  	assert.Regexp(t, "^process\\.args must have at least one entry$", err.Error())
   209  }
   210  
   211  func TestHasBindMountsAndCommands(t *testing.T) {
   212  	hasBindMounts := true
   213  	when := When{
   214  		HasBindMounts: &hasBindMounts,
   215  		Commands: []string{
   216  			"^/bin/sh$",
   217  		},
   218  	}
   219  	config := &rspec.Spec{Process: &rspec.Process{}}
   220  	for _, tt := range []struct {
   221  		name          string
   222  		command       string
   223  		hasBindMounts bool
   224  		or            bool
   225  		match         bool
   226  	}{
   227  		{
   228  			name:          "both, and",
   229  			command:       "/bin/sh",
   230  			hasBindMounts: true,
   231  			or:            false,
   232  			match:         true,
   233  		},
   234  		{
   235  			name:          "both, or",
   236  			command:       "/bin/sh",
   237  			hasBindMounts: true,
   238  			or:            true,
   239  			match:         true,
   240  		},
   241  		{
   242  			name:          "bind, and",
   243  			command:       "/bin/shell",
   244  			hasBindMounts: true,
   245  			or:            false,
   246  			match:         false,
   247  		},
   248  		{
   249  			name:          "bind, or",
   250  			command:       "/bin/shell",
   251  			hasBindMounts: true,
   252  			or:            true,
   253  			match:         true,
   254  		},
   255  		{
   256  			name:          "command, and",
   257  			command:       "/bin/sh",
   258  			hasBindMounts: false,
   259  			or:            false,
   260  			match:         false,
   261  		},
   262  		{
   263  			name:          "command, or",
   264  			command:       "/bin/sh",
   265  			hasBindMounts: false,
   266  			or:            true,
   267  			match:         true,
   268  		},
   269  		{
   270  			name:          "neither, and",
   271  			command:       "/bin/shell",
   272  			hasBindMounts: false,
   273  			or:            false,
   274  			match:         false,
   275  		},
   276  		{
   277  			name:          "neither, or",
   278  			command:       "/bin/shell",
   279  			hasBindMounts: false,
   280  			or:            true,
   281  			match:         false,
   282  		},
   283  	} {
   284  		test := tt
   285  		t.Run(test.name, func(t *testing.T) {
   286  			config.Process.Args = []string{test.command}
   287  			when.Or = test.or
   288  			match, err := when.Match(config, map[string]string{}, test.hasBindMounts)
   289  			if err != nil {
   290  				t.Fatal(err)
   291  			}
   292  			assert.Equal(t, test.match, match)
   293  		})
   294  	}
   295  }
   296  
   297  func TestInvalidRegexp(t *testing.T) {
   298  	config := &rspec.Spec{Process: &rspec.Process{Args: []string{"/bin/sh"}}}
   299  	for _, tt := range []struct {
   300  		name     string
   301  		when     When
   302  		expected string
   303  	}{
   304  		{
   305  			name:     "invalid-annotation-key",
   306  			when:     When{Annotations: map[string]string{"[": "a"}},
   307  			expected: "^annotation key: error parsing regexp: .*",
   308  		},
   309  		{
   310  			name:     "invalid-annotation-value",
   311  			when:     When{Annotations: map[string]string{"a": "["}},
   312  			expected: "^annotation value: error parsing regexp: .*",
   313  		},
   314  		{
   315  			name:     "invalid-command",
   316  			when:     When{Commands: []string{"["}},
   317  			expected: "^command: error parsing regexp: .*",
   318  		},
   319  	} {
   320  		test := tt
   321  		t.Run(test.name, func(t *testing.T) {
   322  			_, err := test.when.Match(config, map[string]string{"a": "b"}, false)
   323  			if err == nil {
   324  				t.Fatal("unexpected success")
   325  			}
   326  			assert.Regexp(t, test.expected, err.Error())
   327  		})
   328  	}
   329  }