Skip to content

Commit 101dea7

Browse files
committed
Copy OmitEmpty tests to OmitZero tests
Signed-off-by: Jordan Liggitt <[email protected]>
1 parent 167dc75 commit 101dea7

File tree

1 file changed

+387
-0
lines changed

1 file changed

+387
-0
lines changed

encode_test.go

Lines changed: 387 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1597,6 +1597,393 @@ func TestOmitEmptyForBigInt(t *testing.T) {
15971597
testRoundTrip(t, []roundTripTest{{"default values", v, want}}, em, dm)
15981598
}
15991599

1600+
func TestOmitZeroForBuiltinType(t *testing.T) {
1601+
type T struct {
1602+
B bool `cbor:"b"`
1603+
Bo bool `cbor:"bo,omitzero"`
1604+
UI uint `cbor:"ui"`
1605+
UIo uint `cbor:"uio,omitzero"`
1606+
I int `cbor:"i"`
1607+
Io int `cbor:"io,omitzero"`
1608+
F float64 `cbor:"f"`
1609+
Fo float64 `cbor:"fo,omitzero"`
1610+
S string `cbor:"s"`
1611+
So string `cbor:"so,omitzero"`
1612+
Slc []string `cbor:"slc"`
1613+
Slco []string `cbor:"slco,omitzero"`
1614+
M map[int]string `cbor:"m"`
1615+
Mo map[int]string `cbor:"mo,omitzero"`
1616+
P *int `cbor:"p"`
1617+
Po *int `cbor:"po,omitzero"`
1618+
Intf any `cbor:"intf"`
1619+
Intfo any `cbor:"intfo,omitzero"`
1620+
}
1621+
1622+
v := T{}
1623+
// {"b": false, "ui": 0, "i":0, "f": 0, "s": "", "slc": null, "m": {}, "p": nil, "intf": nil }
1624+
want := []byte{0xa9,
1625+
0x61, 0x62, 0xf4,
1626+
0x62, 0x75, 0x69, 0x00,
1627+
0x61, 0x69, 0x00,
1628+
0x61, 0x66, 0xfb, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1629+
0x61, 0x73, 0x60,
1630+
0x63, 0x73, 0x6c, 0x63, 0xf6,
1631+
0x61, 0x6d, 0xf6,
1632+
0x61, 0x70, 0xf6,
1633+
0x64, 0x69, 0x6e, 0x74, 0x66, 0xf6,
1634+
}
1635+
1636+
em, _ := EncOptions{}.EncMode()
1637+
dm, _ := DecOptions{}.DecMode()
1638+
testRoundTrip(t, []roundTripTest{{"default values", v, want}}, em, dm)
1639+
}
1640+
1641+
func TestOmitZeroForAnonymousStruct(t *testing.T) {
1642+
type T struct {
1643+
Str struct{} `cbor:"str"`
1644+
Stro struct{} `cbor:"stro,omitzero"`
1645+
}
1646+
1647+
v := T{}
1648+
want := []byte{0xa1, 0x63, 0x73, 0x74, 0x72, 0xa0} // {"str": {}}
1649+
1650+
em, _ := EncOptions{}.EncMode()
1651+
dm, _ := DecOptions{}.DecMode()
1652+
testRoundTrip(t, []roundTripTest{{"default values", v, want}}, em, dm)
1653+
}
1654+
1655+
func TestOmitZeroForStruct1(t *testing.T) {
1656+
type T1 struct {
1657+
Bo bool `cbor:"bo,omitzero"`
1658+
UIo uint `cbor:"uio,omitzero"`
1659+
Io int `cbor:"io,omitzero"`
1660+
Fo float64 `cbor:"fo,omitzero"`
1661+
So string `cbor:"so,omitzero"`
1662+
Slco []string `cbor:"slco,omitzero"`
1663+
Mo map[int]string `cbor:"mo,omitzero"`
1664+
Po *int `cbor:"po,omitzero"`
1665+
Intfo any `cbor:"intfo,omitzero"`
1666+
}
1667+
type T struct {
1668+
Str T1 `cbor:"str"`
1669+
Stro T1 `cbor:"stro,omitzero"`
1670+
}
1671+
1672+
v := T{}
1673+
want := []byte{0xa1, 0x63, 0x73, 0x74, 0x72, 0xa0} // {"str": {}}
1674+
1675+
em, _ := EncOptions{}.EncMode()
1676+
dm, _ := DecOptions{}.DecMode()
1677+
testRoundTrip(t, []roundTripTest{{"default values", v, want}}, em, dm)
1678+
}
1679+
1680+
func TestOmitZeroForStruct2(t *testing.T) {
1681+
type T1 struct {
1682+
Bo bool `cbor:"bo,omitzero"`
1683+
UIo uint `cbor:"uio,omitzero"`
1684+
Io int `cbor:"io,omitzero"`
1685+
Fo float64 `cbor:"fo,omitzero"`
1686+
So string `cbor:"so,omitzero"`
1687+
Slco []string `cbor:"slco,omitzero"`
1688+
Mo map[int]string `cbor:"mo,omitzero"`
1689+
Po *int `cbor:"po,omitzero"`
1690+
Intfo any `cbor:"intfo"`
1691+
}
1692+
type T struct {
1693+
Stro T1 `cbor:"stro,omitzero"`
1694+
}
1695+
1696+
v := T{}
1697+
want := []byte{0xa1, 0x64, 0x73, 0x74, 0x72, 0x6f, 0xa1, 0x65, 0x69, 0x6e, 0x74, 0x66, 0x6f, 0xf6} // {"stro": {intfo: nil}}
1698+
1699+
em, _ := EncOptions{}.EncMode()
1700+
dm, _ := DecOptions{}.DecMode()
1701+
testRoundTrip(t, []roundTripTest{{"non-default values", v, want}}, em, dm)
1702+
}
1703+
1704+
func TestOmitZeroForNestedStruct(t *testing.T) {
1705+
type T1 struct {
1706+
Bo bool `cbor:"bo,omitzero"`
1707+
UIo uint `cbor:"uio,omitzero"`
1708+
Io int `cbor:"io,omitzero"`
1709+
Fo float64 `cbor:"fo,omitzero"`
1710+
So string `cbor:"so,omitzero"`
1711+
Slco []string `cbor:"slco,omitzero"`
1712+
Mo map[int]string `cbor:"mo,omitzero"`
1713+
Po *int `cbor:"po,omitzero"`
1714+
Intfo any `cbor:"intfo,omitzero"`
1715+
}
1716+
type T2 struct {
1717+
Stro T1 `cbor:"stro,omitzero"`
1718+
}
1719+
type T struct {
1720+
Str T2 `cbor:"str"`
1721+
Stro T2 `cbor:"stro,omitzero"`
1722+
}
1723+
1724+
v := T{}
1725+
want := []byte{0xa1, 0x63, 0x73, 0x74, 0x72, 0xa0} // {"str": {}}
1726+
1727+
em, _ := EncOptions{}.EncMode()
1728+
dm, _ := DecOptions{}.DecMode()
1729+
testRoundTrip(t, []roundTripTest{{"default values", v, want}}, em, dm)
1730+
}
1731+
1732+
func TestOmitZeroForToArrayStruct1(t *testing.T) {
1733+
type T1 struct {
1734+
_ struct{} `cbor:",toarray"`
1735+
b bool
1736+
ui uint
1737+
i int
1738+
f float64
1739+
s string
1740+
slc []string
1741+
m map[int]string
1742+
p *int
1743+
intf any
1744+
}
1745+
type T struct {
1746+
Str T1 `cbor:"str"`
1747+
Stro T1 `cbor:"stro,omitzero"`
1748+
}
1749+
1750+
v := T{
1751+
Str: T1{b: false, ui: 0, i: 0, f: 0.0, s: "", slc: nil, m: nil, p: nil, intf: nil},
1752+
Stro: T1{b: false, ui: 0, i: 0, f: 0.0, s: "", slc: nil, m: nil, p: nil, intf: nil},
1753+
}
1754+
want := []byte{0xa1, 0x63, 0x73, 0x74, 0x72, 0x80} // {"str": []}
1755+
1756+
em, _ := EncOptions{}.EncMode()
1757+
dm, _ := DecOptions{}.DecMode()
1758+
testRoundTrip(t, []roundTripTest{{"no exportable fields", v, want}}, em, dm)
1759+
}
1760+
1761+
func TestOmitZeroForToArrayStruct2(t *testing.T) {
1762+
type T1 struct {
1763+
_ struct{} `cbor:",toarray"`
1764+
Bo bool `cbor:"bo"`
1765+
UIo uint `cbor:"uio"`
1766+
Io int `cbor:"io"`
1767+
Fo float64 `cbor:"fo"`
1768+
So string `cbor:"so"`
1769+
Slco []string `cbor:"slco"`
1770+
Mo map[int]string `cbor:"mo"`
1771+
Po *int `cbor:"po"`
1772+
Intfo any `cbor:"intfo"`
1773+
}
1774+
type T struct {
1775+
Stro T1 `cbor:"stro,omitzero"`
1776+
}
1777+
1778+
v := T{}
1779+
// {"stro": [false, 0, 0, 0.0, "", [], {}, nil, nil]}
1780+
want := []byte{0xa1, 0x64, 0x73, 0x74, 0x72, 0x6f, 0x89, 0xf4, 0x00, 0x00, 0xfb, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0xf6, 0xf6, 0xf6, 0xf6}
1781+
1782+
em, _ := EncOptions{}.EncMode()
1783+
dm, _ := DecOptions{}.DecMode()
1784+
testRoundTrip(t, []roundTripTest{{"has exportable fields", v, want}}, em, dm)
1785+
}
1786+
1787+
func TestOmitZeroForStructWithPtrToAnonymousField(t *testing.T) {
1788+
type (
1789+
T1 struct {
1790+
X int `cbor:"x,omitzero"`
1791+
Y int `cbor:"y,omitzero"`
1792+
}
1793+
T2 struct {
1794+
*T1
1795+
}
1796+
T struct {
1797+
Stro T2 `cbor:"stro,omitzero"`
1798+
}
1799+
)
1800+
1801+
testCases := []struct {
1802+
name string
1803+
obj any
1804+
wantCborData []byte
1805+
}{
1806+
{
1807+
name: "null pointer to anonymous field",
1808+
obj: T{},
1809+
wantCborData: []byte{0xa0}, // {}
1810+
},
1811+
{
1812+
name: "not-null pointer to anonymous field",
1813+
obj: T{T2{&T1{}}},
1814+
wantCborData: []byte{0xa0}, // {}
1815+
},
1816+
{
1817+
name: "not empty value in field 1",
1818+
obj: T{T2{&T1{X: 1}}},
1819+
wantCborData: []byte{0xa1, 0x64, 0x73, 0x74, 0x72, 0x6f, 0xa1, 0x61, 0x78, 0x01}, // {stro:{x:1}}
1820+
},
1821+
{
1822+
name: "not empty value in field 2",
1823+
obj: T{T2{&T1{Y: 2}}},
1824+
wantCborData: []byte{0xa1, 0x64, 0x73, 0x74, 0x72, 0x6f, 0xa1, 0x61, 0x79, 0x02}, // {stro:{y:2}}
1825+
},
1826+
{
1827+
name: "not empty value in all fields",
1828+
obj: T{T2{&T1{X: 1, Y: 2}}},
1829+
wantCborData: []byte{0xa1, 0x64, 0x73, 0x74, 0x72, 0x6f, 0xa2, 0x61, 0x78, 0x01, 0x61, 0x79, 0x02}, // {stro:{x:1, y:2}}
1830+
},
1831+
}
1832+
1833+
for _, tc := range testCases {
1834+
t.Run(tc.name, func(t *testing.T) {
1835+
b, err := Marshal(tc.obj)
1836+
if err != nil {
1837+
t.Errorf("Marshal(%+v) returned error %v", tc.obj, err)
1838+
}
1839+
if !bytes.Equal(b, tc.wantCborData) {
1840+
t.Errorf("Marshal(%+v) = 0x%x, want 0x%x", tc.obj, b, tc.wantCborData)
1841+
}
1842+
})
1843+
}
1844+
}
1845+
1846+
func TestOmitZeroForStructWithAnonymousField(t *testing.T) {
1847+
type (
1848+
T1 struct {
1849+
X int `cbor:"x,omitzero"`
1850+
Y int `cbor:"y,omitzero"`
1851+
}
1852+
T2 struct {
1853+
T1
1854+
}
1855+
T struct {
1856+
Stro T2 `cbor:"stro,omitzero"`
1857+
}
1858+
)
1859+
1860+
testCases := []struct {
1861+
name string
1862+
obj any
1863+
wantCborData []byte
1864+
}{
1865+
{
1866+
name: "default values",
1867+
obj: T{},
1868+
wantCborData: []byte{0xa0}, // {}
1869+
},
1870+
{
1871+
name: "default values",
1872+
obj: T{T2{T1{}}},
1873+
wantCborData: []byte{0xa0}, // {}
1874+
},
1875+
{
1876+
name: "not empty value in field 1",
1877+
obj: T{T2{T1{X: 1}}},
1878+
wantCborData: []byte{0xa1, 0x64, 0x73, 0x74, 0x72, 0x6f, 0xa1, 0x61, 0x78, 0x01}, // {stro:{x:1}}
1879+
},
1880+
{
1881+
name: "not empty value in field 2",
1882+
obj: T{T2{T1{Y: 2}}},
1883+
wantCborData: []byte{0xa1, 0x64, 0x73, 0x74, 0x72, 0x6f, 0xa1, 0x61, 0x79, 0x02}, // {stro:{y:2}}
1884+
},
1885+
{
1886+
name: "not empty value in all fields",
1887+
obj: T{T2{T1{X: 1, Y: 2}}},
1888+
wantCborData: []byte{0xa1, 0x64, 0x73, 0x74, 0x72, 0x6f, 0xa2, 0x61, 0x78, 0x01, 0x61, 0x79, 0x02}, // {stro:{x:1, y:2}}
1889+
},
1890+
}
1891+
1892+
for _, tc := range testCases {
1893+
t.Run(tc.name, func(t *testing.T) {
1894+
b, err := Marshal(tc.obj)
1895+
if err != nil {
1896+
t.Errorf("Marshal(%+v) returned error %v", tc.obj, err)
1897+
}
1898+
if !bytes.Equal(b, tc.wantCborData) {
1899+
t.Errorf("Marshal(%+v) = 0x%x, want 0x%x", tc.obj, b, tc.wantCborData)
1900+
}
1901+
})
1902+
}
1903+
}
1904+
1905+
func TestOmitZeroForBinaryMarshaler1(t *testing.T) {
1906+
type T1 struct {
1907+
No number `cbor:"no,omitzero"`
1908+
}
1909+
type T struct {
1910+
Str T1 `cbor:"str"`
1911+
Stro T1 `cbor:"stro,omitzero"`
1912+
}
1913+
1914+
testCases := []roundTripTest{
1915+
{
1916+
"empty BinaryMarshaler",
1917+
T1{},
1918+
[]byte{0xa0}, // {}
1919+
},
1920+
{
1921+
"empty struct containing empty BinaryMarshaler",
1922+
T{},
1923+
[]byte{0xa1, 0x63, 0x73, 0x74, 0x72, 0xa0}, // {str: {}}
1924+
},
1925+
}
1926+
1927+
em, _ := EncOptions{}.EncMode()
1928+
dm, _ := DecOptions{}.DecMode()
1929+
testRoundTrip(t, testCases, em, dm)
1930+
}
1931+
1932+
func TestOmitZeroForBinaryMarshaler2(t *testing.T) {
1933+
type T1 struct {
1934+
So stru `cbor:"so,omitzero"`
1935+
}
1936+
type T struct {
1937+
Str T1 `cbor:"str"`
1938+
Stro T1 `cbor:"stro,omitzero"`
1939+
}
1940+
1941+
testCases := []roundTripTest{
1942+
{
1943+
"empty BinaryMarshaler",
1944+
T1{},
1945+
[]byte{0xa0}, // {}
1946+
},
1947+
{
1948+
"empty struct containing empty BinaryMarshaler",
1949+
T{},
1950+
[]byte{0xa1, 0x63, 0x73, 0x74, 0x72, 0xa0}, // {str: {}}
1951+
},
1952+
}
1953+
1954+
em, _ := EncOptions{}.EncMode()
1955+
dm, _ := DecOptions{}.DecMode()
1956+
testRoundTrip(t, testCases, em, dm)
1957+
}
1958+
1959+
// omitzero is a no-op for time.Time.
1960+
func TestOmitZeroForTime(t *testing.T) {
1961+
type T struct {
1962+
Tm time.Time `cbor:"t,omitzero"`
1963+
}
1964+
1965+
v := T{}
1966+
want := []byte{0xa1, 0x61, 0x74, 0xf6} // {"t": nil}
1967+
1968+
em, _ := EncOptions{}.EncMode()
1969+
dm, _ := DecOptions{}.DecMode()
1970+
testRoundTrip(t, []roundTripTest{{"default values", v, want}}, em, dm)
1971+
}
1972+
1973+
// omitzero is a no-op for big.Int.
1974+
func TestOmitZeroForBigInt(t *testing.T) {
1975+
type T struct {
1976+
I big.Int `cbor:"bi,omitzero"`
1977+
}
1978+
1979+
v := T{}
1980+
want := []byte{0xa1, 0x62, 0x62, 0x69, 0xc2, 0x40} // {"bi": 2([])}
1981+
1982+
em, _ := EncOptions{BigIntConvert: BigIntConvertNone}.EncMode()
1983+
dm, _ := DecOptions{}.DecMode()
1984+
testRoundTrip(t, []roundTripTest{{"default values", v, want}}, em, dm)
1985+
}
1986+
16001987
func TestTaggedField(t *testing.T) {
16011988
// A field (T2.X) with a tag dominates untagged field.
16021989
type (

0 commit comments

Comments
 (0)