github.com/koko1123/flow-go-1@v0.29.6/tools/test_monitor/common/utility.go (about) 1 // Package common has helper / utility functions used by all levels of flaky test monitor. 2 package common 3 4 import ( 5 "encoding/json" 6 "errors" 7 "fmt" 8 "io" 9 "io/fs" 10 "os" 11 "reflect" 12 "strconv" 13 "time" 14 ) 15 16 // AssertNoError checks that the passed in error is nil and panics 17 // with the supplied message if that's not the case. 18 // Useful helper to eliminate the need to keep checking for errors. 19 func AssertNoError(err error, panicMessage string) { 20 if err != nil { 21 panic(panicMessage + ": " + err.Error()) 22 } 23 } 24 25 // ConvertToNDecimalPlaces2 converts the supplied numerator and denominator fraction into 26 // a decimal with n decimal places. Works the same way as ConvertToNDecimalPlaces() 27 // but has a float for the numerator. 28 func ConvertToNDecimalPlaces2(n int, numerator float64, denominator int) float64 { 29 return convertToNDecimalPlacesInternal(n, numerator, float64(denominator)) 30 } 31 32 // ConvertToNDecimalPlaces converts the supplied numerator and denominator fraction into 33 // a decimal with n decimal places. 34 func ConvertToNDecimalPlaces(n int, numerator, denominator int) float64 { 35 return convertToNDecimalPlacesInternal(n, float64(numerator), float64(denominator)) 36 } 37 38 func convertToNDecimalPlacesInternal(n int, numerator, denominator float64) float64 { 39 if numerator == 0 || denominator == 0 { 40 return 0 41 } 42 formatSpecifier := "%." + fmt.Sprint(n) + "f" 43 ratioString := fmt.Sprintf(formatSpecifier, numerator/denominator) 44 ratioFloat, err := strconv.ParseFloat(ratioString, 32) 45 AssertNoError(err, "failure parsing string to float") 46 return float64(ratioFloat) 47 } 48 49 func GetCommitSha() string { 50 commitSha := os.Getenv("COMMIT_SHA") 51 if commitSha == "" { 52 panic("COMMIT_SHA can't be empty") 53 } 54 return commitSha 55 } 56 57 func GetRunID() string { 58 runID := os.Getenv("RUN_ID") 59 if runID == "" { 60 panic("RUN_ID can't be empty") 61 } 62 return runID 63 } 64 65 func GetCommitDate() time.Time { 66 commitDate, err := time.Parse(time.RFC3339, os.Getenv("COMMIT_DATE")) 67 AssertNoError(err, "error parsing COMMIT_DATE") 68 return commitDate 69 } 70 71 func GetJobRunDate() time.Time { 72 jobStarted, err := time.Parse(time.RFC3339, os.Getenv("JOB_STARTED")) 73 AssertNoError(err, "error parsing JOB_STARTED") 74 return jobStarted 75 } 76 77 // IsDirEmpty checks if directory is empty (has no files) and return true if it's empty, false otherwise. 78 // Useful for determining whether to delete the failures / exceptions directories 79 // for cases when there were no failures / exceptions. 80 // From https://stackoverflow.com/a/30708914/5719544. 81 func IsDirEmpty(name string) bool { 82 f, err := os.Open(name) 83 AssertNoError(err, "error reading directory") 84 85 defer f.Close() 86 87 _, err = f.Readdirnames(1) 88 if err == io.EOF { 89 return true 90 } 91 AssertNoError(err, "error reading dir contents") 92 return false 93 } 94 95 // DirExists checks if directory exists and return true if it does, false otherwise. 96 func DirExists(path string) bool { 97 _, err := os.Stat(path) 98 99 // directory exists if there is no error 100 if err == nil { 101 return true 102 } 103 104 // directory doesn't exist if error is of specific type 105 if errors.Is(err, fs.ErrNotExist) { 106 return false 107 } 108 109 // should never get to here 110 panic("error checking if directory exists:" + err.Error()) 111 } 112 113 // SaveToFile save test run/summary to local JSON file. 114 func SaveToFile(fileName string, testSummary interface{}) { 115 testSummaryBytes, err := json.MarshalIndent(testSummary, "", " ") 116 AssertNoError(err, "error marshalling json") 117 118 file, err := os.Create(fileName) 119 AssertNoError(err, "error creating "+fileName) 120 defer file.Close() 121 122 _, err = file.Write(testSummaryBytes) 123 AssertNoError(err, "error saving test summary to file") 124 } 125 126 func SaveLinesToFile(fileName string, list interface{}) { 127 sliceType := reflect.TypeOf(list) 128 if sliceType.Kind() != reflect.Slice && sliceType.Kind() != reflect.Array { 129 panic("argument must be an array or slice") 130 } 131 132 file, err := os.Create(fileName) 133 AssertNoError(err, "error creating "+fileName) 134 defer file.Close() 135 136 l := reflect.ValueOf(list) 137 for i := 0; i < l.Len(); i++ { 138 b, err := json.Marshal(l.Index(i).Interface()) 139 AssertNoError(err, "error marshalling json") 140 141 _, err = file.Write(b) 142 AssertNoError(err, "error writing line to file") 143 144 _, err = file.Write([]byte("\n")) 145 AssertNoError(err, "error writing newline") 146 } 147 }