diff --git a/builder/builder_test.go b/builder/builder_test.go new file mode 100644 index 0000000000000000000000000000000000000000..11f32b6b6ff425a053f631d0630e9dbe5a5c8eb0 --- /dev/null +++ b/builder/builder_test.go @@ -0,0 +1,82 @@ +// Copyright (c) Huawei Technologies Co., Ltd. 2020. All rights reserved. +// isula-build licensed under the Mulan PSL v2. +// You can use this software according to the terms and conditions of the Mulan PSL v2. +// You may obtain a copy of Mulan PSL v2 at: +// http://license.coscl.org.cn/MulanPSL2 +// THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR +// PURPOSE. +// See the Mulan PSL v2 for more details. +// Author: Jingxiao Lu +// Create: 2020-07-24 +// Description: Test cases for Builder package + +package builder + +import ( + "context" + "reflect" + "testing" + + "gotest.tools/fs" + + constant "isula.org/isula-build" + pb "isula.org/isula-build/api/services" + "isula.org/isula-build/builder/dockerfile" + "isula.org/isula-build/store" +) + +func TestNewBuilder(t *testing.T) { + tmpDir := fs.NewDir(t, t.Name()) + defer tmpDir.Remove() + + type args struct { + ctx context.Context + store store.Store + req *pb.BuildRequest + runtimePath string + buildDir string + runDir string + } + tests := []struct { + name string + args args + want Builder + wantErr bool + }{ + { + name: "ctr-img", + args: args{ + ctx: context.Background(), + store: store.Store{}, + req: &pb.BuildRequest{BuildType: constant.BuildContainerImageType}, + buildDir: tmpDir.Path(), + runDir: tmpDir.Path(), + }, + want: &dockerfile.Builder{}, + wantErr: false, + }, + { + name: "No supported type", + args: args{ + ctx: context.Background(), + store: store.Store{}, + req: &pb.BuildRequest{BuildType: "Unknown"}, + }, + want: nil, + wantErr: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := NewBuilder(tt.args.ctx, tt.args.store, tt.args.req, tt.args.runtimePath, tt.args.buildDir, tt.args.runDir) + if (err != nil) != tt.wantErr { + t.Errorf("NewBuilder() error = %v, wantErr %v", err, tt.wantErr) + return + } + if reflect.TypeOf(got) != reflect.TypeOf(tt.want) { + t.Errorf("NewBuilder() got = %v, want %v", reflect.TypeOf(got), reflect.TypeOf(tt.want)) + } + }) + } +} diff --git a/builder/dockerfile/builder_test.go b/builder/dockerfile/builder_test.go index 41bf57aaa7d958263dfb1d1d86152c9716764ce8..680afa37810bdf91bc43d16313982ea9b1dc5b70 100644 --- a/builder/dockerfile/builder_test.go +++ b/builder/dockerfile/builder_test.go @@ -17,6 +17,8 @@ import ( "context" "crypto/sha256" "io/ioutil" + "os" + "path/filepath" "reflect" "regexp" "strings" @@ -26,9 +28,12 @@ import ( "gotest.tools/fs" constant "isula.org/isula-build" + pb "isula.org/isula-build/api/services" "isula.org/isula-build/image" "isula.org/isula-build/pkg/logger" "isula.org/isula-build/pkg/parser" + "isula.org/isula-build/store" + testutil "isula.org/isula-build/tests/util" "isula.org/isula-build/util" ) @@ -1181,7 +1186,7 @@ func TestSearchArg(t *testing.T) { } } -func TestPaseRequestBuildArgs(t *testing.T) { +func TestParseRequestBuildArgs(t *testing.T) { var tests = []struct { name string buildArgs []string @@ -1301,3 +1306,89 @@ func TestParseTag(t *testing.T) { assert.Equal(t, tag, tc.tag, tc.name) } } + +func TestNewBuilder(t *testing.T) { + // tmpfs doesn't not support chattr +i to immutable + tmpDir, err := ioutil.TempDir("/var/tmp", t.Name()) + if err != nil { + t.Log(err) + t.FailNow() + } + defer os.RemoveAll(tmpDir) + immutablePath := filepath.Join(tmpDir, "run") + os.Mkdir(immutablePath, 0644) + if err = testutil.Immutable(immutablePath, true); err != nil { + t.Log(err) + t.FailNow() + } + defer testutil.Immutable(immutablePath, false) + + type args struct { + ctx context.Context + store store.Store + req *pb.BuildRequest + runtimePath string + buildDir string + runDir string + } + tests := []struct { + name string + args args + want *Builder + wantErr bool + }{ + { + name: "NewBuilder - decrypts fail - wrong key", + args: args{ + ctx: context.Background(), + store: store.Store{}, + req: &pb.BuildRequest{ + BuildArgs: []string{"foo=bar", "http_proxy=test"}, + EncryptKey: "1", + }, + buildDir: tmpDir, + runDir: tmpDir, + }, + want: nil, + wantErr: true, + }, + { + name: "NewBuilder - wrong rundir", + args: args{ + ctx: context.Background(), + store: store.Store{}, + req: &pb.BuildRequest{}, + buildDir: tmpDir, + runDir: "", + }, + want: nil, + wantErr: true, + }, + { + name: "NewBuilder - parseOutput fail", + args: args{ + ctx: context.Background(), + store: store.Store{}, + req: &pb.BuildRequest{ + Output: "docker-archive:/home/test/aa.tar", + }, + buildDir: tmpDir, + runDir: immutablePath, + }, + want: nil, + wantErr: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := NewBuilder(tt.args.ctx, tt.args.store, tt.args.req, tt.args.runtimePath, tt.args.buildDir, tt.args.runDir) + if (err != nil) != tt.wantErr { + t.Errorf("NewBuilder() error = %v, wantErr %v", err, tt.wantErr) + return + } + if !reflect.DeepEqual(got, tt.want) { + t.Errorf("NewBuilder() got = %v, want %v", got, tt.want) + } + }) + } +} diff --git a/pkg/stack/stack_test.go b/pkg/stack/stack_test.go index 983d3e340c44b0fac6381627c2c7322b928e0f8f..03bac3ae2936d8e3df2b00d7a806d4bafa153fce 100644 --- a/pkg/stack/stack_test.go +++ b/pkg/stack/stack_test.go @@ -33,6 +33,7 @@ import ( "gotest.tools/fs" constant "isula.org/isula-build" + testutil "isula.org/isula-build/tests/util" ) var ( @@ -184,6 +185,34 @@ func TestDumpStack(t *testing.T) { assert.Equal(t, found, true) } +// TestDumpStackWriteFail dumpStack fail at WriteFile to the path +func TestDumpStackWriteFail(t *testing.T) { + tmpDir, err := ioutil.TempDir("/var/tmp", t.Name()) + if err != nil { + t.Log(err) + t.FailNow() + } + defer os.RemoveAll(tmpDir) + if err = testutil.Immutable(tmpDir, true); err != nil { + t.Log(err) + t.FailNow() + } + defer testutil.Immutable(tmpDir, false) + + var regStackLog = regexp.MustCompile(stackLogRegStr) + dumpStack(tmpDir) + + var found bool + items, err := ioutil.ReadDir(tmpDir) + assert.NilError(t, err) + for _, fi := range items { + if regStackLog.MatchString(fi.Name()) { + found = true + } + } + assert.Equal(t, found, false) +} + func TestLogRotate(t *testing.T) { dir := fs.NewDir(t, "TestLogRotate") defer dir.Remove() @@ -204,3 +233,45 @@ func TestLogRotate(t *testing.T) { // logRotate will keep only "maxStackLogs-1" items. Then will the new dumped stack, we have maxStackLogs items assert.Equal(t, len(items), maxStackLogs-1) } + +func TestLogRotateWrongPath(t *testing.T) { + dirPath := "/abc/foo" + if err := logRotate(dirPath); err == nil { + t.FailNow() + } +} + +// TestLogRotateFail fails for rotating old logs for removing +func TestLogRotateFail(t *testing.T) { + tmpDir, err := ioutil.TempDir("/var/tmp", t.Name()) + if err != nil { + t.Log(err) + t.FailNow() + } + defer os.RemoveAll(tmpDir) + + for i := 0; i < maxStackLogs+2; i++ { + fp := filepath.Join(tmpDir, fmt.Sprintf(stackLogFormat, time.Now().Format("2006-01-02T150405+0800"))) + err = ioutil.WriteFile(fp, []byte("goroutines"), constant.DefaultRootFileMode) + assert.NilError(t, err) + time.Sleep(1 * time.Second) + } + items, err := ioutil.ReadDir(tmpDir) + assert.NilError(t, err) + assert.Equal(t, len(items), maxStackLogs+2) + + if err = testutil.Immutable(tmpDir, true); err != nil { + t.Log(err) + t.FailNow() + } + defer testutil.Immutable(tmpDir, false) + + if err = logRotate(tmpDir); err == nil { + t.Log(err) + t.FailNow() + } + items, err = ioutil.ReadDir(tmpDir) + assert.NilError(t, err) + // logRotate failed for immutable dir, so the items are still maxStackLogs+2 + assert.Equal(t, len(items), maxStackLogs+2) +} diff --git a/tests/util/util.go b/tests/util/util.go index c1e4a136b89be9ac081b685e7b3aeae352bc2d99..f385531cf36a4c8139b097d90b4a8eed5845f7ef 100644 --- a/tests/util/util.go +++ b/tests/util/util.go @@ -17,8 +17,11 @@ package util import ( "flag" "fmt" + "os/exec" "strings" "testing" + + "github.com/pkg/errors" ) const ( @@ -53,3 +56,18 @@ func GetTestingArgs(t *testing.T) map[string]string { return args } + +func Immutable(path string, set bool) error { + var op string + if set { + op = "+i" // set immutable + } else { + op = "-i" // set mutable + } + cmd := exec.Command("chattr", op, path) + err := cmd.Run() + if err != nil { + return errors.Wrapf(err, "chattr %s for %s failed", op, path) + } + return nil +}