-
Notifications
You must be signed in to change notification settings - Fork 176
/
utility.go
147 lines (123 loc) · 4.16 KB
/
utility.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
// Package common has helper / utility functions used by all levels of flaky test monitor.
package common
import (
"encoding/json"
"errors"
"fmt"
"io"
"io/fs"
"os"
"reflect"
"strconv"
"time"
)
// AssertNoError checks that the passed in error is nil and panics
// with the supplied message if that's not the case.
// Useful helper to eliminate the need to keep checking for errors.
func AssertNoError(err error, panicMessage string) {
if err != nil {
panic(panicMessage + ": " + err.Error())
}
}
// ConvertToNDecimalPlaces2 converts the supplied numerator and denominator fraction into
// a decimal with n decimal places. Works the same way as ConvertToNDecimalPlaces()
// but has a float for the numerator.
func ConvertToNDecimalPlaces2(n int, numerator float64, denominator int) float64 {
return convertToNDecimalPlacesInternal(n, numerator, float64(denominator))
}
// ConvertToNDecimalPlaces converts the supplied numerator and denominator fraction into
// a decimal with n decimal places.
func ConvertToNDecimalPlaces(n int, numerator, denominator int) float64 {
return convertToNDecimalPlacesInternal(n, float64(numerator), float64(denominator))
}
func convertToNDecimalPlacesInternal(n int, numerator, denominator float64) float64 {
if numerator == 0 || denominator == 0 {
return 0
}
formatSpecifier := "%." + fmt.Sprint(n) + "f"
ratioString := fmt.Sprintf(formatSpecifier, numerator/denominator)
ratioFloat, err := strconv.ParseFloat(ratioString, 32)
AssertNoError(err, "failure parsing string to float")
return float64(ratioFloat)
}
func GetCommitSha() string {
commitSha := os.Getenv("COMMIT_SHA")
if commitSha == "" {
panic("COMMIT_SHA can't be empty")
}
return commitSha
}
func GetRunID() string {
runID := os.Getenv("RUN_ID")
if runID == "" {
panic("RUN_ID can't be empty")
}
return runID
}
func GetCommitDate() time.Time {
commitDate, err := time.Parse(time.RFC3339, os.Getenv("COMMIT_DATE"))
AssertNoError(err, "error parsing COMMIT_DATE")
return commitDate
}
func GetJobRunDate() time.Time {
jobStarted, err := time.Parse(time.RFC3339, os.Getenv("JOB_STARTED"))
AssertNoError(err, "error parsing JOB_STARTED")
return jobStarted
}
// IsDirEmpty checks if directory is empty (has no files) and return true if it's empty, false otherwise.
// Useful for determining whether to delete the failures / exceptions directories
// for cases when there were no failures / exceptions.
// From https://stackoverflow.com/a/30708914/5719544.
func IsDirEmpty(name string) bool {
f, err := os.Open(name)
AssertNoError(err, "error reading directory")
defer f.Close()
_, err = f.Readdirnames(1)
if err == io.EOF {
return true
}
AssertNoError(err, "error reading dir contents")
return false
}
// DirExists checks if directory exists and return true if it does, false otherwise.
func DirExists(path string) bool {
_, err := os.Stat(path)
// directory exists if there is no error
if err == nil {
return true
}
// directory doesn't exist if error is of specific type
if errors.Is(err, fs.ErrNotExist) {
return false
}
// should never get to here
panic("error checking if directory exists:" + err.Error())
}
// SaveToFile save test run/summary to local JSON file.
func SaveToFile(fileName string, testSummary interface{}) {
testSummaryBytes, err := json.MarshalIndent(testSummary, "", " ")
AssertNoError(err, "error marshalling json")
file, err := os.Create(fileName)
AssertNoError(err, "error creating "+fileName)
defer file.Close()
_, err = file.Write(testSummaryBytes)
AssertNoError(err, "error saving test summary to file")
}
func SaveLinesToFile(fileName string, list interface{}) {
sliceType := reflect.TypeOf(list)
if sliceType.Kind() != reflect.Slice && sliceType.Kind() != reflect.Array {
panic("argument must be an array or slice")
}
file, err := os.Create(fileName)
AssertNoError(err, "error creating "+fileName)
defer file.Close()
l := reflect.ValueOf(list)
for i := 0; i < l.Len(); i++ {
b, err := json.Marshal(l.Index(i).Interface())
AssertNoError(err, "error marshalling json")
_, err = file.Write(b)
AssertNoError(err, "error writing line to file")
_, err = file.Write([]byte("\n"))
AssertNoError(err, "error writing newline")
}
}