github.com/blixtra/rkt@v0.8.1-0.20160204105720-ab0d1add1a43/stage1/init/common/pod_test.go (about)

     1  // Copyright 2014 The rkt Authors
     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 common
    16  
    17  import (
    18  	"io/ioutil"
    19  	"os"
    20  	"regexp"
    21  	"testing"
    22  
    23  	stage1commontypes "github.com/coreos/rkt/stage1/common/types"
    24  
    25  	"github.com/appc/spec/schema"
    26  	"github.com/appc/spec/schema/types"
    27  )
    28  
    29  const tstprefix = "pod-test"
    30  
    31  func TestQuoteExec(t *testing.T) {
    32  	tests := []struct {
    33  		input  []string
    34  		output string
    35  	}{
    36  		{
    37  			input:  []string{`path`, `"arg1"`, `"'arg2'"`, `'arg3'`},
    38  			output: `"path" "\"arg1\"" "\"\'arg2\'\"" "\'arg3\'"`,
    39  		}, {
    40  			input:  []string{`path`},
    41  			output: `"path"`,
    42  		}, {
    43  			input:  []string{`path`, ``, `arg2`},
    44  			output: `"path" "" "arg2"`,
    45  		}, {
    46  			input:  []string{`path`, `"foo\bar"`, `\`},
    47  			output: `"path" "\"foo\\bar\"" "\\"`,
    48  		}, {
    49  			input:  []string{`path with spaces`, `"foo\bar"`, `\`},
    50  			output: `"path with spaces" "\"foo\\bar\"" "\\"`,
    51  		}, {
    52  			input:  []string{`path with "quo't'es" and \slashes`, `"arg"`, `\`},
    53  			output: `"path with \"quo\'t\'es\" and \\slashes" "\"arg\"" "\\"`,
    54  		}, {
    55  			input:  []string{`$path$`, `$argument`},
    56  			output: `"$path$" "$$argument"`,
    57  		}, {
    58  			input:  []string{`path`, `Args\nwith\nnewlines`},
    59  			output: `"path" "Args\\nwith\\nnewlines"`,
    60  		}, {
    61  			input:  []string{`path`, "Args\nwith\nnewlines"},
    62  			output: `"path" "Args\nwith\nnewlines"`,
    63  		},
    64  	}
    65  
    66  	for i, tt := range tests {
    67  		o := quoteExec(tt.input)
    68  		if o != tt.output {
    69  			t.Errorf("#%d: expected `%v` got `%v`", i, tt.output, o)
    70  		}
    71  	}
    72  }
    73  
    74  // TestAppToNspawnArgsOverridesImageManifestReadOnly tests
    75  // that the ImageManifest's `readOnly` volume setting will be
    76  // overrided by PodManifest.
    77  func TestAppToNspawnArgsOverridesImageManifestReadOnly(t *testing.T) {
    78  	falseVar := false
    79  	trueVar := true
    80  	tests := []struct {
    81  		imageManifestVolumeReadOnly bool
    82  		podManifestVolumeReadOnly   *bool
    83  		expectReadOnly              bool
    84  	}{
    85  		{
    86  			false,
    87  			nil,
    88  			false,
    89  		},
    90  		{
    91  			false,
    92  			&falseVar,
    93  			false,
    94  		},
    95  		{
    96  			false,
    97  			&trueVar,
    98  			true,
    99  		},
   100  		{
   101  			true,
   102  			nil,
   103  			true,
   104  		},
   105  		{
   106  			true,
   107  			&falseVar,
   108  			false,
   109  		},
   110  		{
   111  			true,
   112  			&trueVar,
   113  			true,
   114  		},
   115  	}
   116  
   117  	for i, tt := range tests {
   118  		podManifest := &schema.PodManifest{
   119  			Volumes: []types.Volume{
   120  				{
   121  					Name:     *types.MustACName("foo-mount"),
   122  					Kind:     "host",
   123  					Source:   "/host/foo",
   124  					ReadOnly: tt.podManifestVolumeReadOnly,
   125  				},
   126  			},
   127  		}
   128  		appManifest := &schema.RuntimeApp{
   129  			Mounts: []schema.Mount{
   130  				{
   131  					Volume: *types.MustACName("foo-mount"),
   132  					Path:   "/app/foo",
   133  				},
   134  			},
   135  			App: &types.App{
   136  				Exec:  []string{"/bin/foo"},
   137  				User:  "0",
   138  				Group: "0",
   139  				MountPoints: []types.MountPoint{
   140  					{
   141  						Name:     *types.MustACName("foo-mount"),
   142  						Path:     "/app/foo",
   143  						ReadOnly: tt.imageManifestVolumeReadOnly,
   144  					},
   145  				},
   146  			},
   147  		}
   148  
   149  		tmpDir, err := ioutil.TempDir("", tstprefix)
   150  		if err != nil {
   151  			t.Errorf("error creating tempdir: %v", err)
   152  		}
   153  		defer os.RemoveAll(tmpDir)
   154  
   155  		p := &stage1commontypes.Pod{Manifest: podManifest, Root: tmpDir}
   156  		output, err := appToNspawnArgs(p, appManifest)
   157  		if err != nil {
   158  			t.Errorf("#%d: unexpected error: `%v`", i, err)
   159  		}
   160  
   161  		if ro := hasBindROArg(output); ro != tt.expectReadOnly {
   162  			t.Errorf("#%d: expected: readOnly: %v, saw: %v", i, tt.expectReadOnly, ro)
   163  		}
   164  	}
   165  }
   166  
   167  func hasBindROArg(output []string) bool {
   168  	roRegexp := regexp.MustCompile("^--bind-ro=/host/foo:.*/app/foo$")
   169  	for i := len(output) - 1; i >= 0; i-- {
   170  		if roRegexp.MatchString(output[i]) {
   171  			return true
   172  		}
   173  	}
   174  	return false
   175  }