|
|
|
import 'dart:async';
|
|
|
|
|
|
|
|
import 'package:doublefeel_flutter/core/result/app_result.dart';
|
|
|
|
import 'package:doublefeel_flutter/core/services/health_raw_data_core_service.dart';
|
|
|
|
import 'package:doublefeel_flutter/data/datasource/health/health_local_data_convert.dart';
|
|
...
|
...
|
@@ -7,6 +9,12 @@ import 'package:doublefeel_flutter/pigeon/health_kit_api.g.dart'; |
|
|
|
import 'package:doublefeel_flutter/pigeon/health_kit_raw_data_api.g.dart';
|
|
|
|
import 'package:flutter_test/flutter_test.dart';
|
|
|
|
|
|
|
|
Future<void> _pumpAsyncUploads() async {
|
|
|
|
for (var i = 0; i < 6; i += 1) {
|
|
|
|
await Future<void>.delayed(Duration.zero);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void main() {
|
|
|
|
test('sync reads raw data, calculates, stores, and resumes with context',
|
|
|
|
() async {
|
|
...
|
...
|
@@ -330,6 +338,7 @@ void main() { |
|
|
|
endTime: startSeconds + 240,
|
|
|
|
readChunkDays: 1,
|
|
|
|
);
|
|
|
|
await _pumpAsyncUploads();
|
|
|
|
|
|
|
|
expect(
|
|
|
|
operationLog.indexOf('upsertDailyStressPoints'),
|
|
...
|
...
|
@@ -508,6 +517,7 @@ void main() { |
|
|
|
)),
|
|
|
|
readChunkDays: 1,
|
|
|
|
);
|
|
|
|
await _pumpAsyncUploads();
|
|
|
|
final rows = await store.debugQueryAllRows(42);
|
|
|
|
|
|
|
|
expect(api.sleepUploadCallCount, 1);
|
|
...
|
...
|
@@ -570,6 +580,7 @@ void main() { |
|
|
|
endTime: base + 40,
|
|
|
|
readChunkDays: 1,
|
|
|
|
);
|
|
|
|
await _pumpAsyncUploads();
|
|
|
|
final rows = await store.debugQueryAllRows(42);
|
|
|
|
|
|
|
|
expect(result.hrvStressPoints, isEmpty);
|
|
...
|
...
|
@@ -585,6 +596,52 @@ void main() { |
|
|
|
expect(rows.sleepRows.single['uploaded'], 1);
|
|
|
|
});
|
|
|
|
|
|
|
|
test('startCoreCaculate does not wait for pending uploads', () async {
|
|
|
|
const base = 1800000000;
|
|
|
|
final api = _FakeHealthKitRawDataHostApi()
|
|
|
|
..hrvUploadCompleter = Completer<int>()
|
|
|
|
..hrUploadCompleter = Completer<int>();
|
|
|
|
final store = _MemoryHealthRawStressLocalStore();
|
|
|
|
await store.upsertResult(
|
|
|
|
HealthRawStressCalculationResult(
|
|
|
|
userId: 42,
|
|
|
|
hrvStressPoints: [_hrvStressPoint(base + 10)],
|
|
|
|
realtimeStressPoints: [_realtimeStressPoint(base + 20)],
|
|
|
|
dailyStressPoints: const <HealthRawDailyStressPoint>[],
|
|
|
|
),
|
|
|
|
);
|
|
|
|
final service = HealthRawDataCoreService(
|
|
|
|
healthApi: _FakeHealthKitHostApi(),
|
|
|
|
rawDataApi: api,
|
|
|
|
localStore: store,
|
|
|
|
userIdProvider: () => 42,
|
|
|
|
);
|
|
|
|
|
|
|
|
final calculation = service.startCoreCaculate(
|
|
|
|
endTime: base + 40,
|
|
|
|
readChunkDays: 1,
|
|
|
|
);
|
|
|
|
await _pumpAsyncUploads();
|
|
|
|
|
|
|
|
await expectLater(
|
|
|
|
calculation.timeout(const Duration(seconds: 1)),
|
|
|
|
completes,
|
|
|
|
);
|
|
|
|
expect(api.hrvUploadCallCount, 1);
|
|
|
|
expect(api.hrUploadCallCount, 1);
|
|
|
|
var rows = await store.debugQueryAllRows(42);
|
|
|
|
expect(rows.hrvRows.single['uploaded'], 0);
|
|
|
|
expect(rows.realtimeRows.single['uploaded'], 0);
|
|
|
|
|
|
|
|
api.hrvUploadCompleter!.complete(base + 10);
|
|
|
|
api.hrUploadCompleter!.complete(base + 20);
|
|
|
|
await _pumpAsyncUploads();
|
|
|
|
rows = await store.debugQueryAllRows(42);
|
|
|
|
|
|
|
|
expect(rows.hrvRows.single['uploaded'], 1);
|
|
|
|
expect(rows.realtimeRows.single['uploaded'], 1);
|
|
|
|
});
|
|
|
|
|
|
|
|
test('local data source returns earliest local hr start time', () async {
|
|
|
|
const base = 1800000000;
|
|
|
|
final api = _FakeHealthKitRawDataHostApi();
|
|
...
|
...
|
@@ -678,6 +735,8 @@ class _FakeHealthKitRawDataHostApi extends HealthKitRawDataHostApi { |
|
|
|
var hrvUploadUntil = 0;
|
|
|
|
var dailyStressUploadUntil = 0;
|
|
|
|
var sleepUploadUntil = 0;
|
|
|
|
Completer<int>? hrUploadCompleter;
|
|
|
|
Completer<int>? hrvUploadCompleter;
|
|
|
|
var hasData = true;
|
|
|
|
|
|
|
|
void setPoints(int dataType, List<HealthKitRawDataPoint> points) {
|
|
...
|
...
|
@@ -718,12 +777,20 @@ class _FakeHealthKitRawDataHostApi extends HealthKitRawDataHostApi { |
|
|
|
@override
|
|
|
|
Future<int> performHRDataUpload({required String sqliteFilePath}) async {
|
|
|
|
hrUploadCallCount += 1;
|
|
|
|
final completer = hrUploadCompleter;
|
|
|
|
if (completer != null) {
|
|
|
|
return completer.future;
|
|
|
|
}
|
|
|
|
return hrUploadUntil;
|
|
|
|
}
|
|
|
|
|
|
|
|
@override
|
|
|
|
Future<int> performHRVDataUpload({required String sqliteFilePath}) async {
|
|
|
|
hrvUploadCallCount += 1;
|
|
|
|
final completer = hrvUploadCompleter;
|
|
|
|
if (completer != null) {
|
|
|
|
return completer.future;
|
|
|
|
}
|
|
|
|
return hrvUploadUntil;
|
|
|
|
}
|
|
|
|
|
...
|
...
|
|