github.com/joomcode/pegomock@v2.9.2-0.20220414140958-14f53b6b2a6c+incompatible/internal/generate_matchers/matcher_generation.go (about) 1 package main 2 3 import ( 4 "fmt" 5 "io/ioutil" 6 "reflect" 7 "strings" 8 ) 9 10 // Generate matchers: 11 // 12 // go generate github.com/petergtz/pegomock/internal/generate_matchers 13 14 //go:generate go run matcher_generation.go 15 //go:generate go fmt ../../matcher_factories.go 16 //go:generate go fmt ../../ginkgo_compatible/matchers.go 17 18 func main() { 19 mustWriteFile("../../matcher_factories.go", GenerateDefaultMatchersFile()) 20 mustWriteFile("../../ginkgo_compatible/matchers.go", GenerateGinkgoMatchersFile()) 21 } 22 23 func mustWriteFile(path string, contents string) { 24 err := ioutil.WriteFile(path, []byte(contents), 0644) 25 if err != nil { 26 panic(err) 27 } 28 } 29 30 func GenerateDefaultMatchersFile() string { 31 contents := `package pegomock 32 33 import ( 34 "reflect" 35 ) 36 ` 37 38 for _, kind := range primitiveKinds { 39 contents += fmt.Sprintf(` 40 func Eq%[1]s(value %[2]s) %[2]s { 41 RegisterMatcher(&EqMatcher{Value: value}) 42 return %[4]s 43 } 44 45 func NotEq%[1]s(value %[2]s) %[2]s { 46 RegisterMatcher(&NotEqMatcher{Value: value}) 47 return %[4]s 48 } 49 50 func Any%[1]s() %[2]s { 51 RegisterMatcher(NewAnyMatcher(reflect.TypeOf(%[3]s))) 52 return %[4]s 53 } 54 55 func %[1]sThat(matcher ArgumentMatcher) %[2]s { 56 RegisterMatcher(matcher) 57 return %[4]s 58 } 59 60 func Eq%[1]sSlice(value []%[2]s) []%[2]s { 61 RegisterMatcher(&EqMatcher{Value: value}) 62 return nil 63 } 64 65 func NotEq%[1]sSlice(value []%[2]s) []%[2]s { 66 RegisterMatcher(&NotEqMatcher{Value: value}) 67 return nil 68 } 69 70 func Any%[1]sSlice() []%[2]s { 71 RegisterMatcher(NewAnyMatcher(reflect.SliceOf(reflect.TypeOf(%[3]s)))) 72 return nil 73 } 74 75 func %[1]sSliceThat(matcher ArgumentMatcher) []%[2]s { 76 RegisterMatcher(matcher) 77 return nil 78 } 79 `, strings.Title(kind.String()), kind.String(), exampleValue(kind), zeroValue(kind)) 80 } 81 82 // hard-coding this for now as interface{} overall works slightly different than other types. 83 return contents + ` 84 func EqInterface(value interface{}) interface{} { 85 RegisterMatcher(&EqMatcher{Value: value}) 86 return nil 87 } 88 89 func NotEqInterface(value interface{}) interface{} { 90 RegisterMatcher(&NotEqMatcher{Value: value}) 91 return nil 92 } 93 94 func AnyInterface() interface{} { 95 RegisterMatcher(NewAnyMatcher(reflect.TypeOf((*interface{})(nil)).Elem())) 96 return nil 97 } 98 99 func InterfaceThat(matcher ArgumentMatcher) interface{} { 100 RegisterMatcher(matcher) 101 return nil 102 } 103 104 func EqInterfaceSlice(value []interface{}) []interface{} { 105 RegisterMatcher(&EqMatcher{Value: value}) 106 return nil 107 } 108 109 func NotEqInterfaceSlice(value []interface{}) []interface{} { 110 RegisterMatcher(&NotEqMatcher{Value: value}) 111 return nil 112 } 113 114 func AnyInterfaceSlice() []interface{} { 115 RegisterMatcher(NewAnyMatcher(reflect.SliceOf(reflect.TypeOf((*interface{})(nil)).Elem()))) 116 return nil 117 } 118 119 func InterfaceSliceThat(matcher ArgumentMatcher) []interface{} { 120 RegisterMatcher(matcher) 121 return nil 122 } 123 ` 124 } 125 126 func GenerateGinkgoMatchersFile() string { 127 contents := `package mock 128 129 import ( 130 "github.com/petergtz/pegomock" 131 ) 132 133 var (` 134 135 for _, kind := range append(primitiveKinds, reflect.Interface) { 136 contents += fmt.Sprintf(` 137 Eq%[1]s = pegomock.Eq%[1]s 138 NotEq%[1]s = pegomock.NotEq%[1]s 139 Any%[1]s = pegomock.Any%[1]s 140 %[1]sThat = pegomock.%[1]sThat 141 Eq%[1]sSlice = pegomock.Eq%[1]sSlice 142 NotEq%[1]sSlice = pegomock.NotEq%[1]sSlice 143 Any%[1]sSlice = pegomock.Any%[1]sSlice 144 %[1]sSliceThat = pegomock.%[1]sSliceThat 145 `, strings.Title(kind.String())) 146 } 147 148 return contents + ` 149 Times = pegomock.Times 150 AtLeast = pegomock.AtLeast 151 AtMost = pegomock.AtMost 152 Never = pegomock.Never 153 Once = pegomock.Once 154 Twice = pegomock.Twice 155 ) 156 ` 157 } 158 159 var primitiveKinds = []reflect.Kind{ 160 reflect.Bool, 161 reflect.Int, 162 reflect.Int8, 163 reflect.Int16, 164 reflect.Int32, 165 reflect.Int64, 166 reflect.Uint, 167 reflect.Uint8, 168 reflect.Uint16, 169 reflect.Uint32, 170 reflect.Uint64, 171 reflect.Uintptr, 172 reflect.Float32, 173 reflect.Float64, 174 reflect.Complex64, 175 reflect.Complex128, 176 reflect.String, 177 } 178 179 // TODO generate: chan, func matchers 180 181 func zeroValue(kind reflect.Kind) string { 182 switch { 183 case kind == reflect.Bool: 184 return `false` 185 case reflect.Int <= kind && kind <= reflect.Complex128: 186 return `0` 187 case kind == reflect.String: 188 return `""` 189 default: 190 return `nil` 191 } 192 } 193 194 func exampleValue(kind reflect.Kind) string { 195 if kind == reflect.Bool || kind == reflect.Int || kind == reflect.String { 196 return zeroValue(kind) 197 } 198 return fmt.Sprintf("(%s)(%s)", kind.String(), zeroValue(kind)) 199 }