|
|
|
1
|
+import 'dart:async';
|
|
|
|
2
|
+
|
|
1
|
import 'package:doublefeel_flutter/core/result/app_result.dart';
|
3
|
import 'package:doublefeel_flutter/core/result/app_result.dart';
|
|
2
|
import 'package:doublefeel_flutter/core/services/health_raw_data_core_service.dart';
|
4
|
import 'package:doublefeel_flutter/core/services/health_raw_data_core_service.dart';
|
|
3
|
import 'package:doublefeel_flutter/data/datasource/health/health_local_data_convert.dart';
|
5
|
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'; |
|
@@ -7,6 +9,12 @@ import 'package:doublefeel_flutter/pigeon/health_kit_api.g.dart'; |
|
7
|
import 'package:doublefeel_flutter/pigeon/health_kit_raw_data_api.g.dart';
|
9
|
import 'package:doublefeel_flutter/pigeon/health_kit_raw_data_api.g.dart';
|
|
8
|
import 'package:flutter_test/flutter_test.dart';
|
10
|
import 'package:flutter_test/flutter_test.dart';
|
|
9
|
|
11
|
|
|
|
|
12
|
+Future<void> _pumpAsyncUploads() async {
|
|
|
|
13
|
+ for (var i = 0; i < 6; i += 1) {
|
|
|
|
14
|
+ await Future<void>.delayed(Duration.zero);
|
|
|
|
15
|
+ }
|
|
|
|
16
|
+}
|
|
|
|
17
|
+
|
|
10
|
void main() {
|
18
|
void main() {
|
|
11
|
test('sync reads raw data, calculates, stores, and resumes with context',
|
19
|
test('sync reads raw data, calculates, stores, and resumes with context',
|
|
12
|
() async {
|
20
|
() async {
|
|
@@ -330,6 +338,7 @@ void main() { |
|
@@ -330,6 +338,7 @@ void main() { |
|
330
|
endTime: startSeconds + 240,
|
338
|
endTime: startSeconds + 240,
|
|
331
|
readChunkDays: 1,
|
339
|
readChunkDays: 1,
|
|
332
|
);
|
340
|
);
|
|
|
|
341
|
+ await _pumpAsyncUploads();
|
|
333
|
|
342
|
|
|
334
|
expect(
|
343
|
expect(
|
|
335
|
operationLog.indexOf('upsertDailyStressPoints'),
|
344
|
operationLog.indexOf('upsertDailyStressPoints'),
|
|
@@ -508,6 +517,7 @@ void main() { |
|
@@ -508,6 +517,7 @@ void main() { |
|
508
|
)),
|
517
|
)),
|
|
509
|
readChunkDays: 1,
|
518
|
readChunkDays: 1,
|
|
510
|
);
|
519
|
);
|
|
|
|
520
|
+ await _pumpAsyncUploads();
|
|
511
|
final rows = await store.debugQueryAllRows(42);
|
521
|
final rows = await store.debugQueryAllRows(42);
|
|
512
|
|
522
|
|
|
513
|
expect(api.sleepUploadCallCount, 1);
|
523
|
expect(api.sleepUploadCallCount, 1);
|
|
@@ -570,6 +580,7 @@ void main() { |
|
@@ -570,6 +580,7 @@ void main() { |
|
570
|
endTime: base + 40,
|
580
|
endTime: base + 40,
|
|
571
|
readChunkDays: 1,
|
581
|
readChunkDays: 1,
|
|
572
|
);
|
582
|
);
|
|
|
|
583
|
+ await _pumpAsyncUploads();
|
|
573
|
final rows = await store.debugQueryAllRows(42);
|
584
|
final rows = await store.debugQueryAllRows(42);
|
|
574
|
|
585
|
|
|
575
|
expect(result.hrvStressPoints, isEmpty);
|
586
|
expect(result.hrvStressPoints, isEmpty);
|
|
@@ -585,6 +596,52 @@ void main() { |
|
@@ -585,6 +596,52 @@ void main() { |
|
585
|
expect(rows.sleepRows.single['uploaded'], 1);
|
596
|
expect(rows.sleepRows.single['uploaded'], 1);
|
|
586
|
});
|
597
|
});
|
|
587
|
|
598
|
|
|
|
|
599
|
+ test('startCoreCaculate does not wait for pending uploads', () async {
|
|
|
|
600
|
+ const base = 1800000000;
|
|
|
|
601
|
+ final api = _FakeHealthKitRawDataHostApi()
|
|
|
|
602
|
+ ..hrvUploadCompleter = Completer<int>()
|
|
|
|
603
|
+ ..hrUploadCompleter = Completer<int>();
|
|
|
|
604
|
+ final store = _MemoryHealthRawStressLocalStore();
|
|
|
|
605
|
+ await store.upsertResult(
|
|
|
|
606
|
+ HealthRawStressCalculationResult(
|
|
|
|
607
|
+ userId: 42,
|
|
|
|
608
|
+ hrvStressPoints: [_hrvStressPoint(base + 10)],
|
|
|
|
609
|
+ realtimeStressPoints: [_realtimeStressPoint(base + 20)],
|
|
|
|
610
|
+ dailyStressPoints: const <HealthRawDailyStressPoint>[],
|
|
|
|
611
|
+ ),
|
|
|
|
612
|
+ );
|
|
|
|
613
|
+ final service = HealthRawDataCoreService(
|
|
|
|
614
|
+ healthApi: _FakeHealthKitHostApi(),
|
|
|
|
615
|
+ rawDataApi: api,
|
|
|
|
616
|
+ localStore: store,
|
|
|
|
617
|
+ userIdProvider: () => 42,
|
|
|
|
618
|
+ );
|
|
|
|
619
|
+
|
|
|
|
620
|
+ final calculation = service.startCoreCaculate(
|
|
|
|
621
|
+ endTime: base + 40,
|
|
|
|
622
|
+ readChunkDays: 1,
|
|
|
|
623
|
+ );
|
|
|
|
624
|
+ await _pumpAsyncUploads();
|
|
|
|
625
|
+
|
|
|
|
626
|
+ await expectLater(
|
|
|
|
627
|
+ calculation.timeout(const Duration(seconds: 1)),
|
|
|
|
628
|
+ completes,
|
|
|
|
629
|
+ );
|
|
|
|
630
|
+ expect(api.hrvUploadCallCount, 1);
|
|
|
|
631
|
+ expect(api.hrUploadCallCount, 1);
|
|
|
|
632
|
+ var rows = await store.debugQueryAllRows(42);
|
|
|
|
633
|
+ expect(rows.hrvRows.single['uploaded'], 0);
|
|
|
|
634
|
+ expect(rows.realtimeRows.single['uploaded'], 0);
|
|
|
|
635
|
+
|
|
|
|
636
|
+ api.hrvUploadCompleter!.complete(base + 10);
|
|
|
|
637
|
+ api.hrUploadCompleter!.complete(base + 20);
|
|
|
|
638
|
+ await _pumpAsyncUploads();
|
|
|
|
639
|
+ rows = await store.debugQueryAllRows(42);
|
|
|
|
640
|
+
|
|
|
|
641
|
+ expect(rows.hrvRows.single['uploaded'], 1);
|
|
|
|
642
|
+ expect(rows.realtimeRows.single['uploaded'], 1);
|
|
|
|
643
|
+ });
|
|
|
|
644
|
+
|
|
588
|
test('local data source returns earliest local hr start time', () async {
|
645
|
test('local data source returns earliest local hr start time', () async {
|
|
589
|
const base = 1800000000;
|
646
|
const base = 1800000000;
|
|
590
|
final api = _FakeHealthKitRawDataHostApi();
|
647
|
final api = _FakeHealthKitRawDataHostApi();
|
|
@@ -678,6 +735,8 @@ class _FakeHealthKitRawDataHostApi extends HealthKitRawDataHostApi { |
|
@@ -678,6 +735,8 @@ class _FakeHealthKitRawDataHostApi extends HealthKitRawDataHostApi { |
|
678
|
var hrvUploadUntil = 0;
|
735
|
var hrvUploadUntil = 0;
|
|
679
|
var dailyStressUploadUntil = 0;
|
736
|
var dailyStressUploadUntil = 0;
|
|
680
|
var sleepUploadUntil = 0;
|
737
|
var sleepUploadUntil = 0;
|
|
|
|
738
|
+ Completer<int>? hrUploadCompleter;
|
|
|
|
739
|
+ Completer<int>? hrvUploadCompleter;
|
|
681
|
var hasData = true;
|
740
|
var hasData = true;
|
|
682
|
|
741
|
|
|
683
|
void setPoints(int dataType, List<HealthKitRawDataPoint> points) {
|
742
|
void setPoints(int dataType, List<HealthKitRawDataPoint> points) {
|
|
@@ -718,12 +777,20 @@ class _FakeHealthKitRawDataHostApi extends HealthKitRawDataHostApi { |
|
@@ -718,12 +777,20 @@ class _FakeHealthKitRawDataHostApi extends HealthKitRawDataHostApi { |
|
718
|
@override
|
777
|
@override
|
|
719
|
Future<int> performHRDataUpload({required String sqliteFilePath}) async {
|
778
|
Future<int> performHRDataUpload({required String sqliteFilePath}) async {
|
|
720
|
hrUploadCallCount += 1;
|
779
|
hrUploadCallCount += 1;
|
|
|
|
780
|
+ final completer = hrUploadCompleter;
|
|
|
|
781
|
+ if (completer != null) {
|
|
|
|
782
|
+ return completer.future;
|
|
|
|
783
|
+ }
|
|
721
|
return hrUploadUntil;
|
784
|
return hrUploadUntil;
|
|
722
|
}
|
785
|
}
|
|
723
|
|
786
|
|
|
724
|
@override
|
787
|
@override
|
|
725
|
Future<int> performHRVDataUpload({required String sqliteFilePath}) async {
|
788
|
Future<int> performHRVDataUpload({required String sqliteFilePath}) async {
|
|
726
|
hrvUploadCallCount += 1;
|
789
|
hrvUploadCallCount += 1;
|
|
|
|
790
|
+ final completer = hrvUploadCompleter;
|
|
|
|
791
|
+ if (completer != null) {
|
|
|
|
792
|
+ return completer.future;
|
|
|
|
793
|
+ }
|
|
727
|
return hrvUploadUntil;
|
794
|
return hrvUploadUntil;
|
|
728
|
}
|
795
|
}
|
|
729
|
|
796
|
|