mirror of
https://github.com/abice/go-enum.git
synced 2026-10-28 16:46:59 +08:00
275 lines
6.8 KiB
Go
275 lines
6.8 KiB
Go
//go:build example
|
|
// +build example
|
|
|
|
package example
|
|
|
|
import (
|
|
"encoding/json"
|
|
"errors"
|
|
"flag"
|
|
"fmt"
|
|
"strings"
|
|
"testing"
|
|
|
|
"github.com/spf13/pflag"
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
type makeTest struct {
|
|
M Make `json:"make"`
|
|
}
|
|
|
|
func TestMake(t *testing.T) {
|
|
assert.Equal(t, "Ford", MakeFord.String())
|
|
assert.Equal(t, "Make(99)", Make(99).String())
|
|
ford := MakeFord
|
|
assert.Implements(t, (*flag.Value)(nil), &ford)
|
|
assert.Implements(t, (*flag.Getter)(nil), &ford)
|
|
assert.Implements(t, (*pflag.Value)(nil), &ford)
|
|
|
|
names := MakeNames()
|
|
assert.Len(t, names, 11)
|
|
}
|
|
|
|
var makeTests = []struct {
|
|
name string
|
|
input string
|
|
output *makeTest
|
|
errorExpected bool
|
|
err error
|
|
caseChanged bool
|
|
}{
|
|
{
|
|
name: "toyota",
|
|
input: `{"make":"Toyota"}`,
|
|
output: &makeTest{M: MakeToyota},
|
|
errorExpected: false,
|
|
err: nil,
|
|
},
|
|
{
|
|
name: "chevy",
|
|
input: `{"make":"Chevy"}`,
|
|
output: &makeTest{M: MakeChevy},
|
|
errorExpected: false,
|
|
err: nil,
|
|
},
|
|
{
|
|
name: "ford",
|
|
input: `{"make":"Ford"}`,
|
|
output: &makeTest{M: MakeFord},
|
|
errorExpected: false,
|
|
err: nil,
|
|
},
|
|
{
|
|
name: "tesla",
|
|
input: `{"make":"Tesla"}`,
|
|
output: &makeTest{M: MakeTesla},
|
|
errorExpected: false,
|
|
err: nil,
|
|
},
|
|
{
|
|
name: "hyundai",
|
|
input: `{"make":"Hyundai"}`,
|
|
output: &makeTest{M: MakeHyundai},
|
|
errorExpected: false,
|
|
err: nil,
|
|
},
|
|
{
|
|
name: "nissan",
|
|
input: `{"make":"Nissan"}`,
|
|
output: &makeTest{M: MakeNissan},
|
|
errorExpected: false,
|
|
err: nil,
|
|
},
|
|
{
|
|
name: "jaguar",
|
|
input: `{"make":"Jaguar"}`,
|
|
output: &makeTest{M: MakeJaguar},
|
|
errorExpected: false,
|
|
err: nil,
|
|
},
|
|
{
|
|
name: "audi",
|
|
input: `{"make":"Audi"}`,
|
|
output: &makeTest{M: MakeAudi},
|
|
errorExpected: false,
|
|
err: nil,
|
|
},
|
|
{
|
|
name: "AUDI",
|
|
input: `{"make":"AUDI"}`,
|
|
output: &makeTest{M: MakeAudi},
|
|
errorExpected: false,
|
|
err: nil,
|
|
caseChanged: true,
|
|
},
|
|
{
|
|
name: "bmw",
|
|
input: `{"make":"BMW"}`,
|
|
output: &makeTest{M: MakeBMW},
|
|
errorExpected: false,
|
|
err: nil,
|
|
},
|
|
{
|
|
name: "mercedes",
|
|
input: `{"make":"Mercedes-Benz"}`,
|
|
output: &makeTest{M: MakeMercedesBenz},
|
|
errorExpected: false,
|
|
err: nil,
|
|
},
|
|
{
|
|
name: "volkswagon",
|
|
input: `{"make":"Volkswagon"}`,
|
|
output: &makeTest{M: MakeVolkswagon},
|
|
errorExpected: false,
|
|
err: nil,
|
|
},
|
|
{
|
|
name: "porsche",
|
|
input: `{"make":"Porsche"}`,
|
|
output: &makeTest{M: MakeVolkswagon},
|
|
errorExpected: true,
|
|
err: errors.New("Porsche is not a valid Make, try [Toyota, Chevy, Ford, Tesla, Hyundai, Nissan, Jaguar, Audi, BMW, Mercedes-Benz, Volkswagon]"),
|
|
},
|
|
}
|
|
|
|
func TestMakeUnmarshal(t *testing.T) {
|
|
for _, test := range makeTests {
|
|
t.Run(test.name, func(tt *testing.T) {
|
|
x := &makeTest{}
|
|
err := json.Unmarshal([]byte(test.input), x)
|
|
if !test.errorExpected {
|
|
require.NoError(tt, err, "failed unmarshalling the json.")
|
|
assert.Equal(tt, test.output.M, x.M)
|
|
|
|
// Values won't be exactly the same, so we just validate that it was unmarshalled correctly.
|
|
if !test.caseChanged {
|
|
// Marshal back
|
|
raw, err := json.Marshal(test.output)
|
|
require.NoError(tt, err, "failed marshalling back to json")
|
|
require.JSONEq(tt, test.input, string(raw), "json didn't match")
|
|
}
|
|
} else {
|
|
require.Error(tt, err)
|
|
assert.EqualError(tt, err, test.err.Error())
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestFlagInterface(t *testing.T) {
|
|
for _, test := range makeTests {
|
|
t.Run(test.name, func(tt *testing.T) {
|
|
if test.output != nil {
|
|
var tmp Make
|
|
m := &tmp
|
|
require.Equal(tt, m.Type(), "Make")
|
|
require.Equal(tt, Make(0), m.Get(), "Unset value should be default")
|
|
require.NoError(tt, m.Set(test.output.M.String()), "failed setting flag value")
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestNoZeroValues(t *testing.T) {
|
|
t.Run("base", func(tt *testing.T) {
|
|
assert.Equal(tt, 20, int(NoZerosStart))
|
|
assert.Equal(tt, 21, int(NoZerosMiddle))
|
|
assert.Equal(tt, 22, int(NoZerosEnd))
|
|
assert.Equal(tt, 23, int(NoZerosPs))
|
|
assert.Equal(tt, 24, int(NoZerosPps))
|
|
assert.Equal(tt, 25, int(NoZerosPpps))
|
|
assert.Equal(tt, "ppps", NoZerosPpps.String())
|
|
assert.Equal(tt, "NoZeros(4)", NoZeros(4).String())
|
|
|
|
assert.Len(tt, NoZerosNames(), 6)
|
|
|
|
_, err := ParseNoZeros("pppps")
|
|
assert.EqualError(tt, err, "pppps is not a valid NoZeros, try [start, middle, end, ps, pps, ppps]")
|
|
|
|
tmp, _ := ParseNoZeros("ppps")
|
|
assert.Equal(tt, NoZerosPpps, tmp)
|
|
|
|
tmp, _ = ParseNoZeros("PppS")
|
|
assert.Equal(tt, NoZerosPpps, tmp)
|
|
|
|
val := map[string]*NoZeros{}
|
|
|
|
err = json.Unmarshal([]byte(`{"nz":"pppps"}`), &val)
|
|
assert.EqualError(tt, err, "pppps is not a valid NoZeros, try [start, middle, end, ps, pps, ppps]")
|
|
})
|
|
|
|
for _, name := range NoZerosNames() {
|
|
t.Run(name, func(tt *testing.T) {
|
|
val := map[string]*NoZeros{}
|
|
|
|
rawJSON := fmt.Sprintf(`{"val":"%s"}`, name)
|
|
|
|
require.NoError(tt, json.Unmarshal([]byte(rawJSON), &val), "Failed unmarshalling no zero")
|
|
marshalled, err := json.Marshal(val)
|
|
require.NoError(tt, err, "failed marshalling back to json")
|
|
require.JSONEq(tt, rawJSON, string(marshalled), "marshalled json did not match")
|
|
|
|
// Flag
|
|
var tmp NoZeros
|
|
nz := &tmp
|
|
require.Equal(tt, nz.Type(), "NoZeros")
|
|
require.Equal(tt, NoZeros(0), nz.Get(), "Unset value should be default")
|
|
require.NoError(tt, nz.Set(name), "failed setting flag value")
|
|
})
|
|
}
|
|
}
|
|
|
|
func BenchmarkMakeParse(b *testing.B) {
|
|
knownItems := map[string]struct {
|
|
input string
|
|
output Make
|
|
err error
|
|
}{
|
|
"cased lookup": {
|
|
input: MakeAudi.String(),
|
|
output: MakeAudi,
|
|
},
|
|
"lowercase lookup": {
|
|
input: strings.ToLower(MakeVolkswagon.String()),
|
|
output: MakeVolkswagon,
|
|
},
|
|
"hyphenated upper": {
|
|
input: strings.ToUpper(MakeMercedesBenz.String()),
|
|
output: MakeMercedesBenz,
|
|
},
|
|
// Leave this in to add an int as string parsing option in future.
|
|
// "numeric": {
|
|
// input: "2",
|
|
// output: MakeChevy,
|
|
// },
|
|
// "last numeric": {
|
|
// input: "20",
|
|
// output: MakeVolkswagon,
|
|
// },
|
|
"failure": {
|
|
input: "xyz",
|
|
output: MakeToyota,
|
|
err: errors.New("xyz is not a valid Make, try [Toyota, Chevy, Ford, Tesla, Hyundai, Nissan, Jaguar, Audi, BMW, Mercedes-Benz, Volkswagon]"),
|
|
},
|
|
}
|
|
|
|
for name, tc := range knownItems {
|
|
b.Run(name, func(b *testing.B) {
|
|
b.ReportAllocs()
|
|
|
|
b.ResetTimer()
|
|
for i := 0; i < b.N; i++ {
|
|
out, err := ParseMake(tc.input)
|
|
assert.Equal(b, tc.output, out)
|
|
if tc.err != nil {
|
|
assert.Error(b, err)
|
|
} else {
|
|
assert.NoError(b, err)
|
|
}
|
|
}
|
|
})
|
|
}
|
|
}
|