1 package common
2
3
4
5
6
7
8
9 import (
10 "bufio"
11 "bytes"
12 "context"
13 "errors"
14 "fmt"
15 "io/ioutil"
16 "net/url"
17 "os"
18 "os/exec"
19 "path"
20 "path/filepath"
21 "reflect"
22 "runtime"
23 "strconv"
24 "strings"
25 "time"
26 )
27
28 var (
29 Timeout = 3 * time.Second
30 ErrTimeout = errors.New("command timed out")
31 )
32
33 type Invoker interface {
34 Command(string, ...string) ([]byte, error)
35 CommandWithContext(context.Context, string, ...string) ([]byte, error)
36 }
37
38 type Invoke struct{}
39
40 func (i Invoke) Command(name string, arg ...string) ([]byte, error) {
41 ctx, cancel := context.WithTimeout(context.Background(), Timeout)
42 defer cancel()
43 return i.CommandWithContext(ctx, name, arg...)
44 }
45
46 func (i Invoke) CommandWithContext(ctx context.Context, name string, arg ...string) ([]byte, error) {
47 cmd := exec.CommandContext(ctx, name, arg...)
48
49 var buf bytes.Buffer
50 cmd.Stdout = &buf
51 cmd.Stderr = &buf
52
53 if err := cmd.Start(); err != nil {
54 return buf.Bytes(), err
55 }
56
57 if err := cmd.Wait(); err != nil {
58 return buf.Bytes(), err
59 }
60
61 return buf.Bytes(), nil
62 }
63
64 type FakeInvoke struct {
65 Suffix string
66 Error error
67 }
68
69
70 func (i FakeInvoke) Command(name string, arg ...string) ([]byte, error) {
71 if i.Error != nil {
72 return []byte{}, i.Error
73 }
74
75 arch := runtime.GOOS
76
77 commandName := filepath.Base(name)
78
79 fname := strings.Join(append([]string{commandName}, arg...), "")
80 fname = url.QueryEscape(fname)
81 fpath := path.Join("testdata", arch, fname)
82 if i.Suffix != "" {
83 fpath += "_" + i.Suffix
84 }
85 if PathExists(fpath) {
86 return ioutil.ReadFile(fpath)
87 }
88 return []byte{}, fmt.Errorf("could not find testdata: %s", fpath)
89 }
90
91 func (i FakeInvoke) CommandWithContext(ctx context.Context, name string, arg ...string) ([]byte, error) {
92 return i.Command(name, arg...)
93 }
94
95 var ErrNotImplementedError = errors.New("not implemented yet")
96
97
98 func ReadFile(filename string) (string, error) {
99 content, err := ioutil.ReadFile(filename)
100
101 if err != nil {
102 return "", err
103 }
104
105 return string(content), nil
106 }
107
108
109
110 func ReadLines(filename string) ([]string, error) {
111 return ReadLinesOffsetN(filename, 0, -1)
112 }
113
114
115
116
117
118
119 func ReadLinesOffsetN(filename string, offset uint, n int) ([]string, error) {
120 f, err := os.Open(filename)
121 if err != nil {
122 return []string{""}, err
123 }
124 defer f.Close()
125
126 var ret []string
127
128 r := bufio.NewReader(f)
129 for i := 0; i < n+int(offset) || n < 0; i++ {
130 line, err := r.ReadString('\n')
131 if err != nil {
132 break
133 }
134 if i < int(offset) {
135 continue
136 }
137 ret = append(ret, strings.Trim(line, "\n"))
138 }
139
140 return ret, nil
141 }
142
143 func IntToString(orig []int8) string {
144 ret := make([]byte, len(orig))
145 size := -1
146 for i, o := range orig {
147 if o == 0 {
148 size = i
149 break
150 }
151 ret[i] = byte(o)
152 }
153 if size == -1 {
154 size = len(orig)
155 }
156
157 return string(ret[0:size])
158 }
159
160 func UintToString(orig []uint8) string {
161 ret := make([]byte, len(orig))
162 size := -1
163 for i, o := range orig {
164 if o == 0 {
165 size = i
166 break
167 }
168 ret[i] = o
169 }
170 if size == -1 {
171 size = len(orig)
172 }
173
174 return string(ret[0:size])
175 }
176
177 func ByteToString(orig []byte) string {
178 n := -1
179 l := -1
180 for i, b := range orig {
181
182 if l == -1 && b == 0 {
183 continue
184 }
185 if l == -1 {
186 l = i
187 }
188
189 if b == 0 {
190 break
191 }
192 n = i + 1
193 }
194 if n == -1 {
195 return string(orig)
196 }
197 return string(orig[l:n])
198 }
199
200
201 func ReadInts(filename string) ([]int64, error) {
202 f, err := os.Open(filename)
203 if err != nil {
204 return []int64{}, err
205 }
206 defer f.Close()
207
208 var ret []int64
209
210 r := bufio.NewReader(f)
211
212
213 line, err := r.ReadString('\n')
214 if err != nil {
215 return []int64{}, err
216 }
217
218 i, err := strconv.ParseInt(strings.Trim(line, "\n"), 10, 32)
219 if err != nil {
220 return []int64{}, err
221 }
222 ret = append(ret, i)
223
224 return ret, nil
225 }
226
227
228 func HexToUint32(hex string) uint32 {
229 vv, _ := strconv.ParseUint(hex, 16, 32)
230 return uint32(vv)
231 }
232
233
234 func mustParseInt32(val string) int32 {
235 vv, _ := strconv.ParseInt(val, 10, 32)
236 return int32(vv)
237 }
238
239
240 func mustParseUint64(val string) uint64 {
241 vv, _ := strconv.ParseInt(val, 10, 64)
242 return uint64(vv)
243 }
244
245
246 func mustParseFloat64(val string) float64 {
247 vv, _ := strconv.ParseFloat(val, 64)
248 return vv
249 }
250
251
252 func StringsHas(target []string, src string) bool {
253 for _, t := range target {
254 if strings.TrimSpace(t) == src {
255 return true
256 }
257 }
258 return false
259 }
260
261
262 func StringsContains(target []string, src string) bool {
263 for _, t := range target {
264 if strings.Contains(t, src) {
265 return true
266 }
267 }
268 return false
269 }
270
271
272 func IntContains(target []int, src int) bool {
273 for _, t := range target {
274 if src == t {
275 return true
276 }
277 }
278 return false
279 }
280
281
282
283 func attributes(m interface{}) map[string]reflect.Type {
284 typ := reflect.TypeOf(m)
285 if typ.Kind() == reflect.Ptr {
286 typ = typ.Elem()
287 }
288
289 attrs := make(map[string]reflect.Type)
290 if typ.Kind() != reflect.Struct {
291 return nil
292 }
293
294 for i := 0; i < typ.NumField(); i++ {
295 p := typ.Field(i)
296 if !p.Anonymous {
297 attrs[p.Name] = p.Type
298 }
299 }
300
301 return attrs
302 }
303
304 func PathExists(filename string) bool {
305 if _, err := os.Stat(filename); err == nil {
306 return true
307 }
308 return false
309 }
310
311
312 func GetEnv(key string, dfault string, combineWith ...string) string {
313 value := os.Getenv(key)
314 if value == "" {
315 value = dfault
316 }
317
318 switch len(combineWith) {
319 case 0:
320 return value
321 case 1:
322 return filepath.Join(value, combineWith[0])
323 default:
324 all := make([]string, len(combineWith)+1)
325 all[0] = value
326 copy(all[1:], combineWith)
327 return filepath.Join(all...)
328 }
329 }
330
331 func HostProc(combineWith ...string) string {
332 return GetEnv("HOST_PROC", "/proc", combineWith...)
333 }
334
335 func HostSys(combineWith ...string) string {
336 return GetEnv("HOST_SYS", "/sys", combineWith...)
337 }
338
339 func HostEtc(combineWith ...string) string {
340 return GetEnv("HOST_ETC", "/etc", combineWith...)
341 }
342
343 func HostVar(combineWith ...string) string {
344 return GetEnv("HOST_VAR", "/var", combineWith...)
345 }
346
347 func HostRun(combineWith ...string) string {
348 return GetEnv("HOST_RUN", "/run", combineWith...)
349 }
350
351 func HostDev(combineWith ...string) string {
352 return GetEnv("HOST_DEV", "/dev", combineWith...)
353 }
354
355
356
357 func MockEnv(key string, value string) func() {
358 original := os.Getenv(key)
359 os.Setenv(key, value)
360 return func() {
361 os.Setenv(key, original)
362 }
363 }
364
365
366
367 func getSysctrlEnv(env []string) []string {
368 foundLC := false
369 for i, line := range env {
370 if strings.HasPrefix(line, "LC_ALL") {
371 env[i] = "LC_ALL=C"
372 foundLC = true
373 }
374 }
375 if !foundLC {
376 env = append(env, "LC_ALL=C")
377 }
378 return env
379 }
380
View as plain text