Skip to content

Commit ebda6ee

Browse files
committed
test: add comprehensive tests for volumes with special characters and edge cases
- Introduced new test cases in volumes_test.go to validate the handling of special characters and long patterns in account addresses. - Added scenarios for UTF-8 characters, patterns with wildcards, and edge cases to ensure accurate filtering and matching behavior. - Enhanced tests for complex query combinations, including $or and $and conditions, to verify expected results across various address formats.
1 parent 792fd4b commit ebda6ee

File tree

1 file changed

+257
-0
lines changed

1 file changed

+257
-0
lines changed

internal/storage/ledger/volumes_test.go

Lines changed: 257 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1382,6 +1382,263 @@ func TestVolumesWithMiddleWildcardPatterns(t *testing.T) {
13821382
})
13831383
}
13841384

1385+
func TestVolumesWithSpecialCharactersAndLongPatterns(t *testing.T) {
1386+
t.Parallel()
1387+
store := newLedgerStore(t)
1388+
now := time.Now()
1389+
ctx := logging.TestingContext()
1390+
1391+
// Create accounts with special characters and long patterns
1392+
tx1 := ledger.NewTransaction().
1393+
WithPostings(
1394+
ledger.NewPosting("world", "région:paris", "COIN", big.NewInt(100)),
1395+
ledger.NewPosting("world", "région:lyon", "COIN", big.NewInt(100)),
1396+
ledger.NewPosting("world", "user-name:test_123", "COIN", big.NewInt(100)),
1397+
ledger.NewPosting("world", "a:b:c:d:e", "COIN", big.NewInt(100)),
1398+
ledger.NewPosting("world", "a:x:c:y:e", "COIN", big.NewInt(100)),
1399+
ledger.NewPosting("world", "org:dept:team:user:role:level", "COIN", big.NewInt(100)),
1400+
).
1401+
WithTimestamp(now)
1402+
require.NoError(t, store.CommitTransaction(ctx, &tx1, nil))
1403+
1404+
pit := now.Add(time.Minute)
1405+
1406+
t.Run("UTF-8 characters in segments - accents", func(t *testing.T) {
1407+
t.Parallel()
1408+
1409+
// Pattern with accent character
1410+
volumes, err := store.Volumes().Paginate(ctx,
1411+
ledgercontroller.OffsetPaginatedQuery[ledgercontroller.GetVolumesOptions]{
1412+
Options: ledgercontroller.ResourceQuery[ledgercontroller.GetVolumesOptions]{
1413+
PIT: &pit,
1414+
Builder: query.Match("account", "région:"),
1415+
},
1416+
},
1417+
)
1418+
require.NoError(t, err)
1419+
require.Len(t, volumes.Data, 2) // région:paris, région:lyon
1420+
})
1421+
1422+
t.Run("special characters - dashes and underscores", func(t *testing.T) {
1423+
t.Parallel()
1424+
1425+
// Exact match with dashes and underscores
1426+
volumes, err := store.Volumes().Paginate(ctx,
1427+
ledgercontroller.OffsetPaginatedQuery[ledgercontroller.GetVolumesOptions]{
1428+
Options: ledgercontroller.ResourceQuery[ledgercontroller.GetVolumesOptions]{
1429+
PIT: &pit,
1430+
Builder: query.Match("account", "user-name:"),
1431+
},
1432+
},
1433+
)
1434+
require.NoError(t, err)
1435+
require.Len(t, volumes.Data, 1)
1436+
require.Equal(t, "user-name:test_123", volumes.Data[0].Account)
1437+
})
1438+
1439+
t.Run("pattern with multiple wildcards in middle - a::c::e", func(t *testing.T) {
1440+
t.Parallel()
1441+
1442+
// Pattern: a::c::e = ["a", "", "c", "", "e"] = 5 segments
1443+
// Should match a:X:c:Y:e
1444+
volumes, err := store.Volumes().Paginate(ctx,
1445+
ledgercontroller.OffsetPaginatedQuery[ledgercontroller.GetVolumesOptions]{
1446+
Options: ledgercontroller.ResourceQuery[ledgercontroller.GetVolumesOptions]{
1447+
PIT: &pit,
1448+
Builder: query.Match("account", "a::c::e"),
1449+
},
1450+
},
1451+
)
1452+
require.NoError(t, err)
1453+
require.Len(t, volumes.Data, 2) // a:b:c:d:e and a:x:c:y:e
1454+
})
1455+
1456+
t.Run("long pattern - 6 segments", func(t *testing.T) {
1457+
t.Parallel()
1458+
1459+
// Pattern: org::::: = 6 segments starting with org
1460+
volumes, err := store.Volumes().Paginate(ctx,
1461+
ledgercontroller.OffsetPaginatedQuery[ledgercontroller.GetVolumesOptions]{
1462+
Options: ledgercontroller.ResourceQuery[ledgercontroller.GetVolumesOptions]{
1463+
PIT: &pit,
1464+
Builder: query.Match("account", "org:::::"),
1465+
},
1466+
},
1467+
)
1468+
require.NoError(t, err)
1469+
require.Len(t, volumes.Data, 1)
1470+
require.Equal(t, "org:dept:team:user:role:level", volumes.Data[0].Account)
1471+
})
1472+
1473+
t.Run("pattern matching specific positions in long address", func(t *testing.T) {
1474+
t.Parallel()
1475+
1476+
// Pattern: org::team::: = ["org", "", "team", "", "", ""] = 6 segments
1477+
// Should match org:X:team:Y:Z:W
1478+
volumes, err := store.Volumes().Paginate(ctx,
1479+
ledgercontroller.OffsetPaginatedQuery[ledgercontroller.GetVolumesOptions]{
1480+
Options: ledgercontroller.ResourceQuery[ledgercontroller.GetVolumesOptions]{
1481+
PIT: &pit,
1482+
Builder: query.Match("account", "org::team:::"),
1483+
},
1484+
},
1485+
)
1486+
require.NoError(t, err)
1487+
require.Len(t, volumes.Data, 1)
1488+
require.Equal(t, "org:dept:team:user:role:level", volumes.Data[0].Account)
1489+
})
1490+
1491+
t.Run("$or with UTF-8 patterns", func(t *testing.T) {
1492+
t.Parallel()
1493+
1494+
volumes, err := store.Volumes().Paginate(ctx,
1495+
ledgercontroller.OffsetPaginatedQuery[ledgercontroller.GetVolumesOptions]{
1496+
Options: ledgercontroller.ResourceQuery[ledgercontroller.GetVolumesOptions]{
1497+
PIT: &pit,
1498+
Builder: query.Or(
1499+
query.Match("account", "région:paris"),
1500+
query.Match("account", "user-name:"),
1501+
),
1502+
},
1503+
},
1504+
)
1505+
require.NoError(t, err)
1506+
require.Len(t, volumes.Data, 2) // région:paris and user-name:test_123
1507+
})
1508+
}
1509+
1510+
func TestVolumesWithEdgeCasePatterns(t *testing.T) {
1511+
t.Parallel()
1512+
store := newLedgerStore(t)
1513+
now := time.Now()
1514+
ctx := logging.TestingContext()
1515+
1516+
// Create accounts with various edge case patterns
1517+
tx1 := ledger.NewTransaction().
1518+
WithPostings(
1519+
ledger.NewPosting("world", "a:b", "COIN", big.NewInt(100)),
1520+
ledger.NewPosting("world", "x:y", "COIN", big.NewInt(100)),
1521+
ledger.NewPosting("world", "single", "COIN", big.NewInt(100)),
1522+
ledger.NewPosting("world", "users:alice", "COIN", big.NewInt(100)),
1523+
ledger.NewPosting("world", "users:bob", "COIN", big.NewInt(100)),
1524+
).
1525+
WithTimestamp(now)
1526+
require.NoError(t, store.CommitTransaction(ctx, &tx1, nil))
1527+
1528+
pit := now.Add(time.Minute)
1529+
1530+
t.Run("pattern with single colon - matches all 2-segment addresses", func(t *testing.T) {
1531+
t.Parallel()
1532+
1533+
// Pattern ":" = ["", ""] = 2 segments with both wildcards
1534+
// Should match all 2-segment addresses: a:b, x:y, users:alice, users:bob
1535+
volumes, err := store.Volumes().Paginate(ctx,
1536+
ledgercontroller.OffsetPaginatedQuery[ledgercontroller.GetVolumesOptions]{
1537+
Options: ledgercontroller.ResourceQuery[ledgercontroller.GetVolumesOptions]{
1538+
PIT: &pit,
1539+
Builder: query.Match("account", ":"),
1540+
},
1541+
},
1542+
)
1543+
require.NoError(t, err)
1544+
require.Len(t, volumes.Data, 4) // a:b, x:y, users:alice, users:bob
1545+
})
1546+
1547+
t.Run("exact address match - users:alice should only match users:alice", func(t *testing.T) {
1548+
t.Parallel()
1549+
1550+
// Exact match "users:alice" (no trailing colon)
1551+
volumes, err := store.Volumes().Paginate(ctx,
1552+
ledgercontroller.OffsetPaginatedQuery[ledgercontroller.GetVolumesOptions]{
1553+
Options: ledgercontroller.ResourceQuery[ledgercontroller.GetVolumesOptions]{
1554+
PIT: &pit,
1555+
Builder: query.Match("account", "users:alice"),
1556+
},
1557+
},
1558+
)
1559+
require.NoError(t, err)
1560+
require.Len(t, volumes.Data, 1)
1561+
require.Equal(t, "users:alice", volumes.Data[0].Account)
1562+
})
1563+
1564+
t.Run("double negation - $not($not(partial)) equals partial", func(t *testing.T) {
1565+
t.Parallel()
1566+
1567+
// NOT(NOT(users:)) should equal users:
1568+
volumes, err := store.Volumes().Paginate(ctx,
1569+
ledgercontroller.OffsetPaginatedQuery[ledgercontroller.GetVolumesOptions]{
1570+
Options: ledgercontroller.ResourceQuery[ledgercontroller.GetVolumesOptions]{
1571+
PIT: &pit,
1572+
Builder: query.Not(query.Not(query.Match("account", "users:"))),
1573+
},
1574+
},
1575+
)
1576+
require.NoError(t, err)
1577+
// Should return users:alice, users:bob (same as just "users:")
1578+
require.Len(t, volumes.Data, 2)
1579+
})
1580+
1581+
t.Run("$and with multiple partials - intersection", func(t *testing.T) {
1582+
t.Parallel()
1583+
1584+
// AND of two partials that have no intersection
1585+
// "users:" AND "a:" - no account matches both
1586+
volumes, err := store.Volumes().Paginate(ctx,
1587+
ledgercontroller.OffsetPaginatedQuery[ledgercontroller.GetVolumesOptions]{
1588+
Options: ledgercontroller.ResourceQuery[ledgercontroller.GetVolumesOptions]{
1589+
PIT: &pit,
1590+
Builder: query.And(
1591+
query.Match("account", "users:"),
1592+
query.Match("account", "a:"),
1593+
),
1594+
},
1595+
},
1596+
)
1597+
require.NoError(t, err)
1598+
// No account can match both "users:X" AND "a:X" patterns
1599+
require.Len(t, volumes.Data, 0)
1600+
})
1601+
1602+
t.Run("single segment address - no colon", func(t *testing.T) {
1603+
t.Parallel()
1604+
1605+
// "single" is a 1-segment address (no colon)
1606+
// Exact match should work
1607+
volumes, err := store.Volumes().Paginate(ctx,
1608+
ledgercontroller.OffsetPaginatedQuery[ledgercontroller.GetVolumesOptions]{
1609+
Options: ledgercontroller.ResourceQuery[ledgercontroller.GetVolumesOptions]{
1610+
PIT: &pit,
1611+
Builder: query.Match("account", "single"),
1612+
},
1613+
},
1614+
)
1615+
require.NoError(t, err)
1616+
require.Len(t, volumes.Data, 1)
1617+
require.Equal(t, "single", volumes.Data[0].Account)
1618+
})
1619+
1620+
t.Run("$or with exact and partial - exact takes priority", func(t *testing.T) {
1621+
t.Parallel()
1622+
1623+
// OR("users:alice", "users:") - both match users:alice
1624+
// Should return both users without duplicates
1625+
volumes, err := store.Volumes().Paginate(ctx,
1626+
ledgercontroller.OffsetPaginatedQuery[ledgercontroller.GetVolumesOptions]{
1627+
Options: ledgercontroller.ResourceQuery[ledgercontroller.GetVolumesOptions]{
1628+
PIT: &pit,
1629+
Builder: query.Or(
1630+
query.Match("account", "users:alice"),
1631+
query.Match("account", "users:"),
1632+
),
1633+
},
1634+
},
1635+
)
1636+
require.NoError(t, err)
1637+
// Should return users:alice, users:bob (no duplicates)
1638+
require.Len(t, volumes.Data, 2)
1639+
})
1640+
}
1641+
13851642
func TestVolumesWithComplexNestedQueries(t *testing.T) {
13861643
t.Parallel()
13871644
store := newLedgerStore(t)

0 commit comments

Comments
 (0)