| package humanize |
| |
| import ( |
| "fmt" |
| "math/rand" |
| "reflect" |
| "regexp" |
| "strconv" |
| "strings" |
| "testing" |
| "testing/quick" |
| ) |
| |
| func TestFtoa(t *testing.T) { |
| testList{ |
| {"200", Ftoa(200), "200"}, |
| {"20", Ftoa(20.0), "20"}, |
| {"2", Ftoa(2), "2"}, |
| {"2.2", Ftoa(2.2), "2.2"}, |
| {"2.02", Ftoa(2.02), "2.02"}, |
| {"200.02", Ftoa(200.02), "200.02"}, |
| }.validate(t) |
| } |
| |
| func TestFtoaWithDigits(t *testing.T) { |
| testList{ |
| {"1.23, 0", FtoaWithDigits(1.23, 0), "1"}, |
| {"20, 0", FtoaWithDigits(20.0, 0), "20"}, |
| {"1.23, 1", FtoaWithDigits(1.23, 1), "1.2"}, |
| {"1.23, 2", FtoaWithDigits(1.23, 2), "1.23"}, |
| {"1.23, 3", FtoaWithDigits(1.23, 3), "1.23"}, |
| }.validate(t) |
| } |
| |
| func TestStripTrailingDigits(t *testing.T) { |
| err := quick.Check(func(s string, digits int) bool { |
| stripped := stripTrailingDigits(s, digits) |
| |
| // A stripped string will always be a prefix of its original string |
| if !strings.HasPrefix(s, stripped) { |
| return false |
| } |
| |
| if strings.ContainsRune(s, '.') { |
| // If there is a dot, the part on the left of the dot will never change |
| a := strings.Split(s, ".") |
| b := strings.Split(stripped, ".") |
| if a[0] != b[0] { |
| return false |
| } |
| } else { |
| // If there's no dot in the input, the output will always be the same as the input. |
| if stripped != s { |
| return false |
| } |
| } |
| |
| return true |
| }, &quick.Config{ |
| MaxCount: 10000, |
| Values: func(v []reflect.Value, r *rand.Rand) { |
| rdigs := func(n int) string { |
| digs := []rune{'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'} |
| var rv []rune |
| for i := 0; i < n; i++ { |
| rv = append(rv, digs[r.Intn(len(digs))]) |
| } |
| return string(rv) |
| } |
| |
| ls := r.Intn(20) |
| rs := r.Intn(20) |
| jc := "." |
| if rs == 0 { |
| jc = "" |
| } |
| s := rdigs(ls) + jc + rdigs(rs) |
| digits := r.Intn(len(s) + 1) |
| |
| v[0] = reflect.ValueOf(s) |
| v[1] = reflect.ValueOf(digits) |
| }, |
| }) |
| |
| if err != nil { |
| t.Error(err) |
| } |
| } |
| |
| func BenchmarkFtoaRegexTrailing(b *testing.B) { |
| trailingZerosRegex := regexp.MustCompile(`\.?0+$`) |
| |
| b.ResetTimer() |
| for i := 0; i < b.N; i++ { |
| trailingZerosRegex.ReplaceAllString("2.00000", "") |
| trailingZerosRegex.ReplaceAllString("2.0000", "") |
| trailingZerosRegex.ReplaceAllString("2.000", "") |
| trailingZerosRegex.ReplaceAllString("2.00", "") |
| trailingZerosRegex.ReplaceAllString("2.0", "") |
| trailingZerosRegex.ReplaceAllString("2", "") |
| } |
| } |
| |
| func BenchmarkFtoaFunc(b *testing.B) { |
| for i := 0; i < b.N; i++ { |
| stripTrailingZeros("2.00000") |
| stripTrailingZeros("2.0000") |
| stripTrailingZeros("2.000") |
| stripTrailingZeros("2.00") |
| stripTrailingZeros("2.0") |
| stripTrailingZeros("2") |
| } |
| } |
| |
| func BenchmarkFmtF(b *testing.B) { |
| for i := 0; i < b.N; i++ { |
| _ = fmt.Sprintf("%f", 2.03584) |
| } |
| } |
| |
| func BenchmarkStrconvF(b *testing.B) { |
| for i := 0; i < b.N; i++ { |
| strconv.FormatFloat(2.03584, 'f', 6, 64) |
| } |
| } |