Skip to content

Commit e951b90

Browse files
piatoss3612Thunnini
authored andcommitted
Test RPC latency refresh state
1 parent f235b72 commit e951b90

4 files changed

Lines changed: 103 additions & 8 deletions

File tree

lib/src/core/config/rpc_endpoint_config.dart

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,8 +62,8 @@ class RpcEndpointPreset {
6262
String get hostPort => rpcEndpointHostPort(url);
6363
}
6464

65-
// Mirrors the current zodl-android lightwalletd candidate list while keeping
66-
// this app's existing zec.rocks default unchanged.
65+
// Additional regional lightwalletd presets while keeping this app's existing
66+
// zec.rocks default unchanged.
6767
final kMainnetRpcEndpointPresets = List<RpcEndpointPreset>.unmodifiable([
6868
RpcEndpointPreset(
6969
id: kDefaultRpcEndpointPresetId,

lib/src/providers/rpc_endpoint_latency_provider.dart

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -120,16 +120,17 @@ class RpcEndpointLatencyNotifier extends Notifier<RpcEndpointLatencyState> {
120120
required RpcEndpointChainNameGetter getChainName,
121121
required int generation,
122122
}) async {
123+
final normalizedUrl = normalizeRpcEndpointUrl(
124+
preset.url,
125+
allowDefaultPort: true,
126+
);
123127
final sample = await measureRpcEndpointLatency(
124-
lightwalletdUrl: normalizeRpcEndpointUrl(
125-
preset.url,
126-
allowDefaultPort: true,
127-
),
128+
lightwalletdUrl: normalizedUrl,
128129
expectedNetworkName: networkName,
129130
getChainName: getChainName,
130131
);
131132
if (generation != _generation) return;
132-
state = state.copyWithSample(preset.url, sample);
133+
state = state.copyWithSample(normalizedUrl, sample);
133134
}
134135
}
135136

test/core/config/rpc_endpoint_config_test.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ void main() {
5757
});
5858

5959
group('preset lookup', () {
60-
test('mainnet presets include the zodl endpoint list', () {
60+
test('mainnet presets include the regional endpoint list', () {
6161
final urls = kMainnetRpcEndpointPresets
6262
.map((preset) => preset.url)
6363
.map((url) => normalizeRpcEndpointUrl(url, allowDefaultPort: true))

test/providers/rpc_endpoint_latency_provider_test.dart

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
1+
import 'dart:async';
2+
13
import 'package:flutter_test/flutter_test.dart';
4+
import 'package:flutter_riverpod/flutter_riverpod.dart';
25
import 'package:zcash_wallet/src/providers/rpc_endpoint_latency_provider.dart';
36

47
void main() {
@@ -47,4 +50,95 @@ void main() {
4750
expect(sample.label, 'Unavailable');
4851
});
4952
});
53+
54+
group('RpcEndpointLatencyNotifier', () {
55+
test('marks presets checking before resolving measured latency', () async {
56+
final completer = Completer<String>();
57+
final container = ProviderContainer(
58+
overrides: [
59+
rpcEndpointChainNameGetterProvider.overrideWithValue(
60+
(_) => completer.future,
61+
),
62+
],
63+
);
64+
addTearDown(container.dispose);
65+
66+
final refresh = container
67+
.read(rpcEndpointLatencyProvider.notifier)
68+
.refresh('main');
69+
70+
await Future<void>.delayed(Duration.zero);
71+
72+
final checkingState = container.read(rpcEndpointLatencyProvider);
73+
expect(
74+
checkingState.samples.values.every(
75+
(sample) => sample.status == RpcEndpointLatencyStatus.checking,
76+
),
77+
isTrue,
78+
);
79+
80+
completer.complete('main');
81+
await refresh;
82+
83+
final finalState = container.read(rpcEndpointLatencyProvider);
84+
expect(
85+
finalState.samples.values.every(
86+
(sample) => sample.status == RpcEndpointLatencyStatus.available,
87+
),
88+
isTrue,
89+
);
90+
});
91+
92+
test('discard stale samples when a newer refresh starts', () async {
93+
final completers = <Completer<String>>[];
94+
final container = ProviderContainer(
95+
overrides: [
96+
rpcEndpointChainNameGetterProvider.overrideWithValue((_) {
97+
final completer = Completer<String>();
98+
completers.add(completer);
99+
return completer.future;
100+
}),
101+
],
102+
);
103+
addTearDown(container.dispose);
104+
105+
final firstRefresh = container
106+
.read(rpcEndpointLatencyProvider.notifier)
107+
.refresh('main');
108+
await Future<void>.delayed(Duration.zero);
109+
final firstCompleters = List<Completer<String>>.of(completers);
110+
111+
final secondRefresh = container
112+
.read(rpcEndpointLatencyProvider.notifier)
113+
.refresh('main');
114+
await Future<void>.delayed(Duration.zero);
115+
final secondCompleters = completers
116+
.where((completer) => !firstCompleters.contains(completer))
117+
.toList();
118+
119+
for (final completer in firstCompleters) {
120+
completer.complete('test');
121+
}
122+
await firstRefresh;
123+
final afterStale = container.read(rpcEndpointLatencyProvider);
124+
expect(
125+
afterStale.samples.values.every(
126+
(sample) => sample.status == RpcEndpointLatencyStatus.checking,
127+
),
128+
isTrue,
129+
);
130+
131+
for (final completer in secondCompleters) {
132+
completer.complete('main');
133+
}
134+
await secondRefresh;
135+
final finalState = container.read(rpcEndpointLatencyProvider);
136+
expect(
137+
finalState.samples.values.every(
138+
(sample) => sample.status == RpcEndpointLatencyStatus.available,
139+
),
140+
isTrue,
141+
);
142+
});
143+
});
50144
}

0 commit comments

Comments
 (0)