java-topology/defects/cake_wallet-0001/test/test_cake_wallet_0001.dart

78 lines
2.5 KiB
Dart

/// Unit test for cake_wallet-0001: exchange_view_model token injection
/// dedup uses List.any() O(T*L) instead of Set O(T).
///
/// Simulates the _injectUserEthTokensIntoCurrencyLists pattern with
/// List.any() (defect) vs Set.contains() (fix) and measures op-counts.
int opsDefect = 0;
int opsFix = 0;
class FakeToken {
final String contractAddress;
FakeToken(this.contractAddress);
}
/// Defect: linear scan of list for each token (original pattern)
bool listContainsToken(List<FakeToken> list, FakeToken token) {
return list.any((item) {
opsDefect++;
return item.contractAddress.toLowerCase() == token.contractAddress.toLowerCase();
});
}
/// Fix: set-based lookup
bool setContainsToken(Set<String> addrSet, FakeToken token) {
opsFix++;
return addrSet.contains(token.contractAddress.toLowerCase());
}
void main() {
// Simulate: receiveCurrencies has L existing tokens, injecting T new tokens
final sizes = [
[50, 278], // 50 user tokens, 278 existing currencies
[200, 500], // heavy user with many custom tokens
];
for (final pair in sizes) {
final T = pair[0];
final L = pair[1];
// Build existing currencies list
final existingList = List.generate(L, (i) => FakeToken('0x${i.toRadixString(16).padLeft(40, '0')}'));
// Build user tokens (half overlap, half new)
final userTokens = List.generate(T, (i) {
final idx = i < T ~/ 2 ? i : L + i; // first half overlaps, second half new
return FakeToken('0x${idx.toRadixString(16).padLeft(40, '0')}');
});
// --- Defect path ---
opsDefect = 0;
final toAddDefect = <FakeToken>[];
for (final token in userTokens) {
if (!listContainsToken(existingList, token)) {
toAddDefect.add(token);
}
}
// --- Fix path ---
opsFix = 0;
final addrSet = existingList.map((t) => t.contractAddress.toLowerCase()).toSet();
final toAddFix = <FakeToken>[];
for (final token in userTokens) {
if (!setContainsToken(addrSet, token)) {
toAddFix.add(token);
}
}
// Verify correctness
assert(toAddDefect.length == toAddFix.length,
'FAIL: results differ (defect=${toAddDefect.length}, fix=${toAddFix.length})');
final ratio = opsDefect / opsFix;
print('T=$T L=$L: defect=$opsDefect fix=$opsFix ratio=${ratio.toStringAsFixed(1)}x '
'${ratio > 2 ? "PASS" : "FAIL"}');
assert(ratio > 2, 'FAIL: expected significant speedup, got ${ratio}x');
}
print('cake_wallet-0001: ALL PASS');
}