Add unit tests for coerceUint64 and FlexInt.UnmarshalJSON
45 test cases covering: - FlexInt: integer/float/string parsing, truncation behavior, error cases - coerceUint64: nil, float64 (including NaN/Inf), int/int32/int64, uint32/uint64, json.Number, string parsing (whitespace, null, quotes, commas, scientific notation), unsupported types Coverage: 20.5% -> 22.6%
This commit is contained in:
parent
6267554b74
commit
ae3ffc0355
1 changed files with 321 additions and 0 deletions
|
|
@ -3,6 +3,7 @@ package proxmox
|
|||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"math"
|
||||
"testing"
|
||||
)
|
||||
|
||||
|
|
@ -246,6 +247,326 @@ func TestMemoryStatusUnmarshalFlexibleValues(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestFlexIntUnmarshalJSON(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
input string
|
||||
want FlexInt
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "integer",
|
||||
input: "42",
|
||||
want: FlexInt(42),
|
||||
},
|
||||
{
|
||||
name: "zero",
|
||||
input: "0",
|
||||
want: FlexInt(0),
|
||||
},
|
||||
{
|
||||
name: "negative integer",
|
||||
input: "-10",
|
||||
want: FlexInt(-10),
|
||||
},
|
||||
{
|
||||
name: "float truncates",
|
||||
input: "1.5",
|
||||
want: FlexInt(1),
|
||||
},
|
||||
{
|
||||
name: "float 2.9 truncates",
|
||||
input: "2.9",
|
||||
want: FlexInt(2),
|
||||
},
|
||||
{
|
||||
name: "string integer",
|
||||
input: `"123"`,
|
||||
want: FlexInt(123),
|
||||
},
|
||||
{
|
||||
name: "string float",
|
||||
input: `"1.5"`,
|
||||
want: FlexInt(1),
|
||||
},
|
||||
{
|
||||
name: "string float 3.7",
|
||||
input: `"3.7"`,
|
||||
want: FlexInt(3),
|
||||
},
|
||||
{
|
||||
name: "large integer",
|
||||
input: "1000000",
|
||||
want: FlexInt(1000000),
|
||||
},
|
||||
{
|
||||
name: "invalid string",
|
||||
input: `"not a number"`,
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "empty string",
|
||||
input: `""`,
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "invalid json",
|
||||
input: `{invalid}`,
|
||||
wantErr: true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range tests {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
var f FlexInt
|
||||
err := f.UnmarshalJSON([]byte(tc.input))
|
||||
if tc.wantErr {
|
||||
if err == nil {
|
||||
t.Fatalf("expected error, got nil")
|
||||
}
|
||||
return
|
||||
}
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
if f != tc.want {
|
||||
t.Fatalf("got %d, want %d", f, tc.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestCoerceUint64(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
field string
|
||||
value interface{}
|
||||
want uint64
|
||||
wantErr bool
|
||||
}{
|
||||
// nil handling
|
||||
{
|
||||
name: "nil returns zero",
|
||||
field: "test",
|
||||
value: nil,
|
||||
want: 0,
|
||||
},
|
||||
// float64 handling
|
||||
{
|
||||
name: "float64 positive",
|
||||
field: "test",
|
||||
value: float64(100.0),
|
||||
want: 100,
|
||||
},
|
||||
{
|
||||
name: "float64 rounds",
|
||||
field: "test",
|
||||
value: float64(100.6),
|
||||
want: 101,
|
||||
},
|
||||
{
|
||||
name: "float64 negative returns zero",
|
||||
field: "test",
|
||||
value: float64(-10),
|
||||
want: 0,
|
||||
},
|
||||
{
|
||||
name: "float64 zero",
|
||||
field: "test",
|
||||
value: float64(0),
|
||||
want: 0,
|
||||
},
|
||||
{
|
||||
name: "float64 NaN returns error",
|
||||
field: "test",
|
||||
value: math.NaN(),
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "float64 positive infinity returns error",
|
||||
field: "test",
|
||||
value: math.Inf(1),
|
||||
wantErr: true,
|
||||
},
|
||||
// int handling
|
||||
{
|
||||
name: "int positive",
|
||||
field: "test",
|
||||
value: int(42),
|
||||
want: 42,
|
||||
},
|
||||
{
|
||||
name: "int negative returns zero",
|
||||
field: "test",
|
||||
value: int(-5),
|
||||
want: 0,
|
||||
},
|
||||
{
|
||||
name: "int zero",
|
||||
field: "test",
|
||||
value: int(0),
|
||||
want: 0,
|
||||
},
|
||||
// int64 handling
|
||||
{
|
||||
name: "int64 positive",
|
||||
field: "test",
|
||||
value: int64(1000000000000),
|
||||
want: 1000000000000,
|
||||
},
|
||||
{
|
||||
name: "int64 negative returns zero",
|
||||
field: "test",
|
||||
value: int64(-100),
|
||||
want: 0,
|
||||
},
|
||||
// int32 handling
|
||||
{
|
||||
name: "int32 positive",
|
||||
field: "test",
|
||||
value: int32(12345),
|
||||
want: 12345,
|
||||
},
|
||||
{
|
||||
name: "int32 negative returns zero",
|
||||
field: "test",
|
||||
value: int32(-1),
|
||||
want: 0,
|
||||
},
|
||||
// uint32 handling
|
||||
{
|
||||
name: "uint32",
|
||||
field: "test",
|
||||
value: uint32(4294967295),
|
||||
want: 4294967295,
|
||||
},
|
||||
// uint64 handling
|
||||
{
|
||||
name: "uint64",
|
||||
field: "test",
|
||||
value: uint64(18446744073709551615),
|
||||
want: 18446744073709551615,
|
||||
},
|
||||
// json.Number handling
|
||||
{
|
||||
name: "json.Number integer",
|
||||
field: "test",
|
||||
value: json.Number("12345"),
|
||||
want: 12345,
|
||||
},
|
||||
{
|
||||
name: "json.Number float",
|
||||
field: "test",
|
||||
value: json.Number("123.45"),
|
||||
want: 123,
|
||||
},
|
||||
// string handling
|
||||
{
|
||||
name: "string integer",
|
||||
field: "test",
|
||||
value: "12345",
|
||||
want: 12345,
|
||||
},
|
||||
{
|
||||
name: "string with whitespace",
|
||||
field: "test",
|
||||
value: " 12345 ",
|
||||
want: 12345,
|
||||
},
|
||||
{
|
||||
name: "string empty",
|
||||
field: "test",
|
||||
value: "",
|
||||
want: 0,
|
||||
},
|
||||
{
|
||||
name: "string null",
|
||||
field: "test",
|
||||
value: "null",
|
||||
want: 0,
|
||||
},
|
||||
{
|
||||
name: "string NULL uppercase",
|
||||
field: "test",
|
||||
value: "NULL",
|
||||
want: 0,
|
||||
},
|
||||
{
|
||||
name: "string with quotes",
|
||||
field: "test",
|
||||
value: `"12345"`,
|
||||
want: 12345,
|
||||
},
|
||||
{
|
||||
name: "string with single quotes",
|
||||
field: "test",
|
||||
value: `'12345'`,
|
||||
want: 12345,
|
||||
},
|
||||
{
|
||||
name: "string with commas",
|
||||
field: "test",
|
||||
value: "1,000,000",
|
||||
want: 1000000,
|
||||
},
|
||||
{
|
||||
name: "string float notation",
|
||||
field: "test",
|
||||
value: "123.45",
|
||||
want: 123,
|
||||
},
|
||||
{
|
||||
name: "string scientific notation",
|
||||
field: "test",
|
||||
value: "1e6",
|
||||
want: 1000000,
|
||||
},
|
||||
{
|
||||
name: "string scientific notation uppercase",
|
||||
field: "test",
|
||||
value: "1E6",
|
||||
want: 1000000,
|
||||
},
|
||||
{
|
||||
name: "string invalid",
|
||||
field: "test",
|
||||
value: "not a number",
|
||||
wantErr: true,
|
||||
},
|
||||
// unsupported type
|
||||
{
|
||||
name: "unsupported type bool",
|
||||
field: "test",
|
||||
value: true,
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "unsupported type slice",
|
||||
field: "test",
|
||||
value: []int{1, 2, 3},
|
||||
wantErr: true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range tests {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
got, err := coerceUint64(tc.field, tc.value)
|
||||
if tc.wantErr {
|
||||
if err == nil {
|
||||
t.Fatalf("expected error, got nil")
|
||||
}
|
||||
return
|
||||
}
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
if got != tc.want {
|
||||
t.Fatalf("got %d, want %d", got, tc.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// TestMemoryStatusEffectiveAvailable_RegressionIssue435 tests the specific scenarios
|
||||
// reported in GitHub issue #435 where memory calculations incorrectly included cache/buffers
|
||||
func TestMemoryStatusEffectiveAvailable_RegressionIssue435(t *testing.T) {
|
||||
|
|
|
|||
Loading…
Reference in a new issue