-
Notifications
You must be signed in to change notification settings - Fork 89
/
concurrency.go
161 lines (138 loc) · 5.34 KB
/
concurrency.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
// Copyright (c) 2021-2022, Sylabs Inc. All rights reserved.
// This software is licensed under a 3-clause BSD license. Please consult the
// LICENSE.md file distributed with the sources of this project regarding your
// rights to use or distribute this software.
package pull
import (
"os"
"path"
"path/filepath"
"testing"
"github.com/sylabs/singularity/v4/e2e/internal/e2e"
"github.com/sylabs/singularity/v4/internal/pkg/util/fs"
)
func (c ctx) testConcurrencyConfig(t *testing.T) {
tests := []struct {
name string
setting string
value string
expectedExitCode int
}{
{"DownloadConcurrency", "download concurrency", "5", 0},
{"InvalidDownloadConcurrency", "download concurrency", "-1", 255},
{"DownloadPartSize", "download part size", "32768", 0},
{"InvalidDownloadPartSize", "download part size", "-1", 255},
{"DownloadBufferSize", "download buffer size", "65536", 0},
{"InvalidDownloadBufferSize", "download buffer size", "-1", 255},
}
tmpdir, err := os.MkdirTemp(c.env.TestDir, "pull_test.")
if err != nil {
t.Fatalf("Failed to create temporary directory for pull test: %+v", err)
}
defer os.RemoveAll(tmpdir)
tmpConfig := path.Join(tmpdir, "singularity.conf")
err = fs.EnsureFileWithPermission(tmpConfig, 0o600)
if err != nil {
t.Fatalf("while creating temporary config file: %s", err)
}
for _, tt := range tests {
c.env.RunSingularity(
t,
e2e.AsSubtest(tt.name+"-set"),
e2e.WithProfile(e2e.RootProfile),
e2e.WithGlobalOptions("--config", tmpConfig),
e2e.WithCommand("config global"),
e2e.WithArgs("--set", tt.setting, tt.value),
e2e.ExpectExit(tt.expectedExitCode),
)
c.env.RunSingularity(
t,
e2e.AsSubtest(tt.name+"-reset"),
e2e.WithProfile(e2e.RootProfile),
e2e.WithGlobalOptions("--config", tmpConfig),
e2e.WithCommand("config global"),
e2e.WithArgs("--reset", tt.setting),
e2e.ExpectExit(0),
)
}
}
func (c ctx) testConcurrentPulls(t *testing.T) {
const srcURI = "library://alpine:3.11.5"
tests := []struct {
name string
settings map[string]string
envVars []string
expectedExitCode int
}{
// test traditional sequential download
{"Concurrency1Cfg", map[string]string{"download concurrency": "1"}, nil, 0},
// test concurrency 10
{"Concurrency10Cfg", map[string]string{"download concurrency": "10"}, nil, 0},
// test 1/10 goroutines (set via env vars)
{"Concurrency1Env", nil, []string{"SINGULARITY_DOWNLOAD_CONCURRENCY=1"}, 0},
{"Concurrency10Env", nil, []string{"SINGULARITY_DOWNLOAD_CONCURRENCY=10"}, 0},
// test concurrent download with 1 MiB and 8 MiB part size
{"PartSize1MCfg", map[string]string{"download part size": "1048576"}, nil, 0},
{"PartSize8MCfg", map[string]string{"download part size": "8388608"}, nil, 0},
// test concurrent download with 1 MiB and 8 MiB part size (via env vars)
{"PartSize1MEnv", nil, []string{"SINGULARITY_DOWNLOAD_PART_SIZE=1048576"}, 0},
{"PartSize8MEnv", nil, []string{"SINGULARITY_DOWNLOAD_PART_SIZE=8388608"}, 0},
// use 8 byte and 64 KiB buffer size for concurrent downloads
{"BufferSize1Cfg", map[string]string{"download buffer size": "8"}, nil, 0},
{"BufferSize65536Cfg", map[string]string{"download buffer size": "65536"}, nil, 0},
// use 8 byte and 64 KiB buffer size for concurrent downloads (via env vars)
{"BufferSize1Env", nil, []string{"SINGULARITY_DOWNLOAD_BUFFER_SIZE=8"}, 0},
{"BufferSize65536Env", nil, []string{"SINGULARITY_DOWNLOAD_BUFFER_SIZE=65536"}, 0},
// multiple settings (concurrency 1, download buffer size 64 KiB)
{"MultipleSettings", map[string]string{"download concurrency": "1", "download buffer size": "65536"}, nil, 0},
}
for _, tt := range tests {
tt := tt
t.Run(tt.name, func(t *testing.T) {
tmpdir, err := os.MkdirTemp(c.env.TestDir, "pull_test.")
if err != nil {
t.Fatalf("Failed to create temporary directory for pull test: %+v", err)
}
defer os.RemoveAll(tmpdir)
// A new temporary config file for each test, no need to reset when we're done.
tmpConfig := path.Join(tmpdir, "singularity.conf")
err = fs.EnsureFileWithPermission(tmpConfig, 0o600)
if err != nil {
t.Fatalf("while creating temporary config file: %s", err)
}
// Set global configuration
if tt.settings != nil {
cfgCmdOps := []e2e.SingularityCmdOp{
e2e.WithProfile(e2e.RootProfile),
e2e.WithGlobalOptions("--config", tmpConfig),
e2e.WithCommand("config global"),
e2e.ExpectExit(0),
}
for key, value := range tt.settings {
t.Logf("set %s %s", key, value)
cfgCmd := append(cfgCmdOps, e2e.WithArgs("--set", key, value))
c.env.RunSingularity(t, cfgCmd...)
}
}
// Reset global configuration at test completion
ts := testStruct{
desc: "",
srcURI: srcURI,
expectedExitCode: tt.expectedExitCode,
expectedImage: getImageNameFromURI(srcURI, false),
envVars: tt.envVars,
}
// No explicit image path specified. Will use temp dir as working directory,
// so we pull into a clean location.
ts.workDir = tmpdir
imageName := getImageNameFromURI(ts.srcURI, false)
ts.expectedImage = filepath.Join(tmpdir, imageName)
// if there's a pullDir, that's where we expect to find the image
if ts.pullDir != "" {
ts.expectedImage = filepath.Join(ts.pullDir, imageName)
}
// pull image
c.imagePull(t, ts)
})
}
}