[current results ui] Initial version of current results Flutter web interface
This is the initial version of the current results web app.
Change-Id: I4c1da75f1e8ec1e02e2703e96ab5d132f6f3a6c4
Reviewed-on: https://dart-review.googlesource.com/c/dart_ci/+/158441
Reviewed-by: Karl Klose <karlklose@google.com>
diff --git a/ui_current_results/lib/filter.dart b/ui_current_results/lib/filter.dart
new file mode 100644
index 0000000..10911fc
--- /dev/null
+++ b/ui_current_results/lib/filter.dart
@@ -0,0 +1,69 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:flutter/material.dart';
+import 'package:provider/provider.dart';
+
+class Filter extends ChangeNotifier {
+ List<String> terms = [
+ 'dartk-',
+ 'app_jitk',
+ 'service/de',
+ ];
+
+ void addAll(String value) {
+ for (final term in value.split(',')) {
+ final trimmed = term.trim();
+ if (trimmed.isEmpty) continue;
+ if (terms.contains(trimmed)) continue;
+ terms.add(trimmed);
+ }
+ notifyListeners();
+ }
+
+ void remove(String term) {
+ terms.remove(term);
+ notifyListeners();
+ }
+}
+
+class FilterUI extends StatelessWidget {
+ @override
+ Widget build(BuildContext context) {
+ return Consumer<Filter>(
+ builder: (context, filter, child) {
+ return Padding(
+ padding: EdgeInsets.all(8.0),
+ child: Wrap(
+ spacing: 12.0,
+ alignment: WrapAlignment.start,
+ children: [
+ for (final term in filter.terms)
+ InputChip(
+ label: Text(term), onDeleted: () => filter.remove(term)),
+ AddWidget(filter),
+ ],
+ ),
+ );
+ },
+ );
+ }
+}
+
+class AddWidget extends StatelessWidget {
+ final Filter filter;
+ AddWidget(this.filter);
+
+ @override
+ Widget build(BuildContext context) {
+ return SizedBox(
+ width: 200.0,
+ height: 40.0,
+ child: TextField(
+ decoration: InputDecoration(hintText: 'Test or configuration prefix'),
+ onSubmitted: (value) => filter.addAll(value),
+ ),
+ );
+ }
+}
diff --git a/ui_current_results/lib/main.dart b/ui_current_results/lib/main.dart
new file mode 100644
index 0000000..5efcdd4
--- /dev/null
+++ b/ui_current_results/lib/main.dart
@@ -0,0 +1,149 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:clippy/browser.dart' as clippy;
+import 'package:flutter/material.dart';
+import 'package:provider/provider.dart';
+import 'dart:html' as html;
+
+import 'filter.dart';
+import 'query.dart';
+import 'results.dart';
+
+void main() {
+ runApp(CurrentResultsAppProviders());
+}
+
+class CurrentResultsAppProviders extends StatelessWidget {
+ @override
+ Widget build(BuildContext context) {
+ return MaterialApp(
+ title: 'Current Results',
+ theme: ThemeData(
+ primarySwatch: Colors.blue,
+ visualDensity: VisualDensity.compact,
+ ),
+ home: MultiProvider(
+ providers: [
+ ChangeNotifierProvider(create: (context) => Filter()),
+ ChangeNotifierProxyProvider<Filter, QueryResults>(
+ create: (context) => QueryResults(),
+ update: (context, filter, queryResults) {
+ return queryResults
+ ..filter = filter
+ ..fetchCurrentResults();
+ })
+ ],
+ child: DefaultTabController(
+ length: 2,
+ child: CurrentResultsApp(),
+ )));
+ }
+}
+
+class CurrentResultsApp extends StatelessWidget {
+ @override
+ Widget build(BuildContext context) {
+ return Align(
+ alignment: Alignment.topLeft,
+ child: Container(
+ constraints: BoxConstraints(maxWidth: 808.0),
+ decoration: BoxDecoration(
+ border: Border(right: BorderSide(color: Colors.black))),
+ child: Scaffold(
+ appBar: AppBar(
+ leading: Image.asset('dart_64.png', width: 16.0, height: 32.0),
+ title: Text(
+ 'Current Results',
+ style: TextStyle(
+ fontSize: 24.0,
+ color: Color.fromARGB(255, 63, 81, 181),
+ ),
+ ),
+ backgroundColor: Colors.white,
+ bottom: TabBar(
+ tabs: [
+ Tab(text: 'ALL'),
+ Tab(text: 'FAILURES'),
+ ],
+ indicatorColor: Color.fromARGB(255, 63, 81, 181),
+ labelColor: Color.fromARGB(255, 63, 81, 181),
+ ),
+ ),
+ persistentFooterButtons: [
+ JsonLink(),
+ textPopup(),
+ ],
+ body: Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ FilterUI(),
+ Expanded(
+ child: Consumer<QueryResults>(
+ builder: (context, results, child) => TabBarView(
+ children: [
+ ResultsPanel(results, showAll: true),
+ ResultsPanel(results, showAll: false)
+ ],
+ ),
+ ),
+ ),
+ ],
+ ),
+ ),
+ ),
+ );
+ }
+}
+
+class JsonLink extends StatelessWidget {
+ @override
+ Widget build(BuildContext context) => Consumer<Filter>(
+ builder: (context, filter, child) => FlatButton(
+ child: Text('json'),
+ onPressed: () => html.window.open(
+ Uri.https(apiHost, 'v1/results', {
+ 'filter': filter.terms.join(','),
+ 'pageSize': '4000'
+ }).toString(),
+ '_blank'),
+ ),
+ );
+}
+
+Widget textPopup() {
+ return Consumer<QueryResults>(
+ builder: (context, QueryResults results, child) {
+ return FlatButton(
+ child: Text('text'),
+ onPressed: () => showDialog(
+ context: context,
+ builder: (BuildContext context) {
+ final text = [resultTextHeader]
+ .followedBy(
+ results.resultsObject.results.map(resultAsCommaSeparated))
+ .join('\n');
+ return AlertDialog(
+ title: Text('Results query as text'),
+ content: SelectableText(text),
+ actions: <Widget>[
+ FlatButton(
+ child: Text('Copy and dismiss'),
+ onPressed: () {
+ clippy.write(text);
+ Navigator.of(context).pop();
+ },
+ ),
+ FlatButton(
+ child: Text('Dismiss'),
+ onPressed: () => Navigator.of(context).pop(),
+ ),
+ ],
+ );
+ },
+ ),
+ );
+ },
+ );
+}
diff --git a/ui_current_results/lib/query.dart b/ui_current_results/lib/query.dart
new file mode 100644
index 0000000..8e47075
--- /dev/null
+++ b/ui_current_results/lib/query.dart
@@ -0,0 +1,78 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:collection/collection.dart';
+import 'package:flutter/material.dart';
+import 'package:http/http.dart' as http;
+import 'dart:convert';
+
+import 'src/generated/query.pb.dart';
+import 'filter.dart';
+
+const String apiHost = 'current-results-rest-zlujsyuhha-uc.a.run.app';
+// Current endpoints proxy is limited to 1 MB response size,
+// so we limit results fetched to 4000.
+// Implement paging on the service in the future to remove this limit.
+const int fetchLimit = 4000;
+const int maxFetchedResults = 100 * fetchLimit;
+
+class QueryResults extends ChangeNotifier {
+ Filter filter;
+ bool showAll = true;
+ List<String> names = [];
+ Map<String, Map<ChangeInResult, List<Result>>> grouped = {};
+ bool partialResults = true;
+
+ GetResultsResponse resultsObject = GetResultsResponse.create();
+
+ void fetchCurrentResults() async {
+ final client = http.Client();
+ final resultsQuery = Uri.https(apiHost, 'v1/results',
+ {'filter': filter.terms.join(','), 'pageSize': '$fetchLimit'});
+ final resultsResponse = await client.get(resultsQuery);
+ resultsObject = GetResultsResponse.create()
+ ..mergeFromProto3Json(json.decode(resultsResponse.body));
+ final results = resultsObject.results;
+
+ grouped = groupBy<Result, String>(results, (Result result) => result.name)
+ .map((String name, List<Result> list) => MapEntry(name,
+ groupBy<Result, ChangeInResult>(list, ChangeInResult.fromResult)));
+ names = grouped.keys.toList()..sort();
+ partialResults = results.length == fetchLimit;
+ notifyListeners();
+ }
+}
+
+class ChangeInResult {
+ static const Color lightCoral = Color.fromARGB(255, 240, 128, 128);
+ static const Color gold = Color.fromARGB(255, 255, 215, 0);
+
+ String result;
+ String expected;
+ bool flaky;
+ bool get matches => result == expected;
+ Color get backgroundColor =>
+ flaky ? gold : matches ? Colors.lightGreen : lightCoral;
+
+ ChangeInResult._(this.result, this.expected, this.flaky);
+ static ChangeInResult fromResult(Result result) =>
+ ChangeInResult._(result.result, result.expected, result.flaky);
+
+ String toString() => flaky
+ ? "flaky (latest result $result expected $expected"
+ : "$result (expected $expected)";
+ bool operator ==(Object other) => toString() == other.toString();
+ int get hashCode => toString().hashCode;
+}
+
+String resultAsCommaSeparated(Result result) => [
+ result.name,
+ result.configuration,
+ result.result,
+ result.expected,
+ result.flaky,
+ result.timeMs
+ ].join(',');
+
+String resultTextHeader = "name,configuration,result,expected,flaky,timeMs";
diff --git a/ui_current_results/lib/results.dart b/ui_current_results/lib/results.dart
new file mode 100644
index 0000000..6c2fa13
--- /dev/null
+++ b/ui_current_results/lib/results.dart
@@ -0,0 +1,106 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:html' as html;
+
+import 'package:flutter/material.dart';
+
+import 'query.dart';
+
+class ResultsPanel extends StatelessWidget {
+ final QueryResults queryResults;
+ final bool showAll;
+
+ ResultsPanel(this.queryResults, {this.showAll = true});
+
+ @override
+ Widget build(BuildContext context) {
+ return Align(
+ alignment: Alignment.topLeft,
+ child: SizedBox(
+ width: 800.0,
+ child: Container(
+ decoration: BoxDecoration(border: Border.all(color: Colors.black)),
+ child: ListView.builder(
+ itemCount: queryResults.names.length,
+ itemBuilder: itemBuilder(queryResults),
+ ),
+ ),
+ ),
+ );
+ }
+
+ IndexedWidgetBuilder itemBuilder(QueryResults results) {
+ return (BuildContext context, int index) {
+ final name = results.names[index];
+ final changeGroups = results.grouped[name];
+ if (!showAll && changeGroups.keys.every((change) => change.matches)) {
+ // Inserting this seems to break history icons on remaining tests.
+ return Container(height: 0.0, width: 0.0);
+ }
+ return Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ SizedOverflowBox(
+ size: Size(600.0, 18.0),
+ alignment: Alignment.topLeft,
+ child: Padding(
+ padding: EdgeInsets.only(top: 0.0, left: 8.0),
+ child: Row(
+ children: [
+ Flexible(
+ child: SingleChildScrollView(
+ scrollDirection: Axis.horizontal,
+ reverse: true,
+ child: SelectableText(
+ results.partialResults
+ ? '$name (partial results)'
+ : name,
+ style: TextStyle(fontSize: 16.0),
+ ),
+ ),
+ ),
+ IconButton(
+ icon: Icon(Icons.history),
+ onPressed: () => html.window.open(
+ Uri(
+ path: '/',
+ fragment: showAll
+ ? 'showLatestFailures=false&test=$name'
+ : 'test=$name')
+ .toString(),
+ '_blank'),
+ ),
+ ],
+ ),
+ ),
+ ),
+ for (final change
+ in changeGroups.keys.where((key) => showAll || !key.matches))
+ Container(
+ alignment: Alignment.topLeft,
+ constraints: BoxConstraints.loose(Size.fromWidth(500.0)),
+ child: ExpansionTile(
+ key: Key(name + change.toString()),
+ title: Text(
+ '$change (${changeGroups[change].length} configurations)',
+ style: TextStyle(
+ backgroundColor: change.backgroundColor,
+ fontSize: 14.0,
+ ),
+ ),
+ expandedAlignment: Alignment.topLeft,
+ expandedCrossAxisAlignment: CrossAxisAlignment.start,
+ childrenPadding: EdgeInsets.only(left: 48.0, bottom: 4.0),
+ children: [
+ for (final result in changeGroups[change])
+ SelectableText(result.configuration),
+ ],
+ ),
+ ),
+ ],
+ );
+ };
+ }
+}
diff --git a/ui_current_results/lib/src/generated/google/protobuf/empty.pb.dart b/ui_current_results/lib/src/generated/google/protobuf/empty.pb.dart
new file mode 100644
index 0000000..bc2a099
--- /dev/null
+++ b/ui_current_results/lib/src/generated/google/protobuf/empty.pb.dart
@@ -0,0 +1,38 @@
+///
+// Generated code. Do not modify.
+// source: google/protobuf/empty.proto
+//
+// @dart = 2.3
+// ignore_for_file: camel_case_types,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name,return_of_invalid_type
+
+import 'dart:core' as $core;
+
+import 'package:protobuf/protobuf.dart' as $pb;
+
+class Empty extends $pb.GeneratedMessage {
+ static final $pb.BuilderInfo _i = $pb.BuilderInfo('Empty',
+ package: const $pb.PackageName('google.protobuf'),
+ createEmptyInstance: create)
+ ..hasRequiredFields = false;
+
+ Empty._() : super();
+ factory Empty() => create();
+ factory Empty.fromBuffer($core.List<$core.int> i,
+ [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) =>
+ create()..mergeFromBuffer(i, r);
+ factory Empty.fromJson($core.String i,
+ [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) =>
+ create()..mergeFromJson(i, r);
+ Empty clone() => Empty()..mergeFromMessage(this);
+ Empty copyWith(void Function(Empty) updates) =>
+ super.copyWith((message) => updates(message as Empty));
+ $pb.BuilderInfo get info_ => _i;
+ @$core.pragma('dart2js:noInline')
+ static Empty create() => Empty._();
+ Empty createEmptyInstance() => create();
+ static $pb.PbList<Empty> createRepeated() => $pb.PbList<Empty>();
+ @$core.pragma('dart2js:noInline')
+ static Empty getDefault() =>
+ _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<Empty>(create);
+ static Empty _defaultInstance;
+}
diff --git a/ui_current_results/lib/src/generated/google/protobuf/empty.pbenum.dart b/ui_current_results/lib/src/generated/google/protobuf/empty.pbenum.dart
new file mode 100644
index 0000000..0fb3ebb
--- /dev/null
+++ b/ui_current_results/lib/src/generated/google/protobuf/empty.pbenum.dart
@@ -0,0 +1,6 @@
+///
+// Generated code. Do not modify.
+// source: google/protobuf/empty.proto
+//
+// @dart = 2.3
+// ignore_for_file: camel_case_types,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name,return_of_invalid_type
diff --git a/ui_current_results/lib/src/generated/google/protobuf/empty.pbjson.dart b/ui_current_results/lib/src/generated/google/protobuf/empty.pbjson.dart
new file mode 100644
index 0000000..588c6a0
--- /dev/null
+++ b/ui_current_results/lib/src/generated/google/protobuf/empty.pbjson.dart
@@ -0,0 +1,10 @@
+///
+// Generated code. Do not modify.
+// source: google/protobuf/empty.proto
+//
+// @dart = 2.3
+// ignore_for_file: camel_case_types,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name,return_of_invalid_type
+
+const Empty$json = const {
+ '1': 'Empty',
+};
diff --git a/ui_current_results/lib/src/generated/google/protobuf/empty.pbserver.dart b/ui_current_results/lib/src/generated/google/protobuf/empty.pbserver.dart
new file mode 100644
index 0000000..7a64fc1
--- /dev/null
+++ b/ui_current_results/lib/src/generated/google/protobuf/empty.pbserver.dart
@@ -0,0 +1,8 @@
+///
+// Generated code. Do not modify.
+// source: google/protobuf/empty.proto
+//
+// @dart = 2.3
+// ignore_for_file: camel_case_types,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name,return_of_invalid_type
+
+export 'empty.pb.dart';
diff --git a/ui_current_results/lib/src/generated/query.pb.dart b/ui_current_results/lib/src/generated/query.pb.dart
new file mode 100644
index 0000000..c5e7833
--- /dev/null
+++ b/ui_current_results/lib/src/generated/query.pb.dart
@@ -0,0 +1,513 @@
+///
+// Generated code. Do not modify.
+// source: query.proto
+//
+// @dart = 2.3
+// ignore_for_file: camel_case_types,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name,return_of_invalid_type
+
+import 'dart:async' as $async;
+import 'dart:core' as $core;
+
+import 'package:protobuf/protobuf.dart' as $pb;
+
+import 'google/protobuf/empty.pb.dart' as $0;
+
+class GetResultsRequest extends $pb.GeneratedMessage {
+ static final $pb.BuilderInfo _i = $pb.BuilderInfo('GetResultsRequest',
+ package: const $pb.PackageName('current_results'),
+ createEmptyInstance: create)
+ ..pPS(1, 'names')
+ ..pPS(2, 'configurations')
+ ..a<$core.int>(3, 'pageSize', $pb.PbFieldType.O3)
+ ..aOS(4, 'pageToken')
+ ..hasRequiredFields = false;
+
+ GetResultsRequest._() : super();
+ factory GetResultsRequest() => create();
+ factory GetResultsRequest.fromBuffer($core.List<$core.int> i,
+ [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) =>
+ create()..mergeFromBuffer(i, r);
+ factory GetResultsRequest.fromJson($core.String i,
+ [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) =>
+ create()..mergeFromJson(i, r);
+ GetResultsRequest clone() => GetResultsRequest()..mergeFromMessage(this);
+ GetResultsRequest copyWith(void Function(GetResultsRequest) updates) =>
+ super.copyWith((message) => updates(message as GetResultsRequest));
+ $pb.BuilderInfo get info_ => _i;
+ @$core.pragma('dart2js:noInline')
+ static GetResultsRequest create() => GetResultsRequest._();
+ GetResultsRequest createEmptyInstance() => create();
+ static $pb.PbList<GetResultsRequest> createRepeated() =>
+ $pb.PbList<GetResultsRequest>();
+ @$core.pragma('dart2js:noInline')
+ static GetResultsRequest getDefault() => _defaultInstance ??=
+ $pb.GeneratedMessage.$_defaultFor<GetResultsRequest>(create);
+ static GetResultsRequest _defaultInstance;
+
+ @$pb.TagNumber(1)
+ $core.List<$core.String> get names => $_getList(0);
+
+ @$pb.TagNumber(2)
+ $core.List<$core.String> get configurations => $_getList(1);
+
+ @$pb.TagNumber(3)
+ $core.int get pageSize => $_getIZ(2);
+ @$pb.TagNumber(3)
+ set pageSize($core.int v) {
+ $_setSignedInt32(2, v);
+ }
+
+ @$pb.TagNumber(3)
+ $core.bool hasPageSize() => $_has(2);
+ @$pb.TagNumber(3)
+ void clearPageSize() => clearField(3);
+
+ @$pb.TagNumber(4)
+ $core.String get pageToken => $_getSZ(3);
+ @$pb.TagNumber(4)
+ set pageToken($core.String v) {
+ $_setString(3, v);
+ }
+
+ @$pb.TagNumber(4)
+ $core.bool hasPageToken() => $_has(3);
+ @$pb.TagNumber(4)
+ void clearPageToken() => clearField(4);
+}
+
+class GetResultsResponse extends $pb.GeneratedMessage {
+ static final $pb.BuilderInfo _i = $pb.BuilderInfo('GetResultsResponse',
+ package: const $pb.PackageName('current_results'),
+ createEmptyInstance: create)
+ ..pc<Result>(1, 'results', $pb.PbFieldType.PM, subBuilder: Result.create)
+ ..aOS(2, 'nextPageToken')
+ ..hasRequiredFields = false;
+
+ GetResultsResponse._() : super();
+ factory GetResultsResponse() => create();
+ factory GetResultsResponse.fromBuffer($core.List<$core.int> i,
+ [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) =>
+ create()..mergeFromBuffer(i, r);
+ factory GetResultsResponse.fromJson($core.String i,
+ [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) =>
+ create()..mergeFromJson(i, r);
+ GetResultsResponse clone() => GetResultsResponse()..mergeFromMessage(this);
+ GetResultsResponse copyWith(void Function(GetResultsResponse) updates) =>
+ super.copyWith((message) => updates(message as GetResultsResponse));
+ $pb.BuilderInfo get info_ => _i;
+ @$core.pragma('dart2js:noInline')
+ static GetResultsResponse create() => GetResultsResponse._();
+ GetResultsResponse createEmptyInstance() => create();
+ static $pb.PbList<GetResultsResponse> createRepeated() =>
+ $pb.PbList<GetResultsResponse>();
+ @$core.pragma('dart2js:noInline')
+ static GetResultsResponse getDefault() => _defaultInstance ??=
+ $pb.GeneratedMessage.$_defaultFor<GetResultsResponse>(create);
+ static GetResultsResponse _defaultInstance;
+
+ @$pb.TagNumber(1)
+ $core.List<Result> get results => $_getList(0);
+
+ @$pb.TagNumber(2)
+ $core.String get nextPageToken => $_getSZ(1);
+ @$pb.TagNumber(2)
+ set nextPageToken($core.String v) {
+ $_setString(1, v);
+ }
+
+ @$pb.TagNumber(2)
+ $core.bool hasNextPageToken() => $_has(1);
+ @$pb.TagNumber(2)
+ void clearNextPageToken() => clearField(2);
+}
+
+class Result extends $pb.GeneratedMessage {
+ static final $pb.BuilderInfo _i = $pb.BuilderInfo('Result',
+ package: const $pb.PackageName('current_results'),
+ createEmptyInstance: create)
+ ..aOS(1, 'name')
+ ..aOS(2, 'configuration')
+ ..aOS(3, 'result')
+ ..aOS(4, 'expected')
+ ..aOB(5, 'flaky')
+ ..a<$core.int>(6, 'timeMs', $pb.PbFieldType.O3)
+ ..hasRequiredFields = false;
+
+ Result._() : super();
+ factory Result() => create();
+ factory Result.fromBuffer($core.List<$core.int> i,
+ [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) =>
+ create()..mergeFromBuffer(i, r);
+ factory Result.fromJson($core.String i,
+ [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) =>
+ create()..mergeFromJson(i, r);
+ Result clone() => Result()..mergeFromMessage(this);
+ Result copyWith(void Function(Result) updates) =>
+ super.copyWith((message) => updates(message as Result));
+ $pb.BuilderInfo get info_ => _i;
+ @$core.pragma('dart2js:noInline')
+ static Result create() => Result._();
+ Result createEmptyInstance() => create();
+ static $pb.PbList<Result> createRepeated() => $pb.PbList<Result>();
+ @$core.pragma('dart2js:noInline')
+ static Result getDefault() =>
+ _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<Result>(create);
+ static Result _defaultInstance;
+
+ @$pb.TagNumber(1)
+ $core.String get name => $_getSZ(0);
+ @$pb.TagNumber(1)
+ set name($core.String v) {
+ $_setString(0, v);
+ }
+
+ @$pb.TagNumber(1)
+ $core.bool hasName() => $_has(0);
+ @$pb.TagNumber(1)
+ void clearName() => clearField(1);
+
+ @$pb.TagNumber(2)
+ $core.String get configuration => $_getSZ(1);
+ @$pb.TagNumber(2)
+ set configuration($core.String v) {
+ $_setString(1, v);
+ }
+
+ @$pb.TagNumber(2)
+ $core.bool hasConfiguration() => $_has(1);
+ @$pb.TagNumber(2)
+ void clearConfiguration() => clearField(2);
+
+ @$pb.TagNumber(3)
+ $core.String get result => $_getSZ(2);
+ @$pb.TagNumber(3)
+ set result($core.String v) {
+ $_setString(2, v);
+ }
+
+ @$pb.TagNumber(3)
+ $core.bool hasResult() => $_has(2);
+ @$pb.TagNumber(3)
+ void clearResult() => clearField(3);
+
+ @$pb.TagNumber(4)
+ $core.String get expected => $_getSZ(3);
+ @$pb.TagNumber(4)
+ set expected($core.String v) {
+ $_setString(3, v);
+ }
+
+ @$pb.TagNumber(4)
+ $core.bool hasExpected() => $_has(3);
+ @$pb.TagNumber(4)
+ void clearExpected() => clearField(4);
+
+ @$pb.TagNumber(5)
+ $core.bool get flaky => $_getBF(4);
+ @$pb.TagNumber(5)
+ set flaky($core.bool v) {
+ $_setBool(4, v);
+ }
+
+ @$pb.TagNumber(5)
+ $core.bool hasFlaky() => $_has(4);
+ @$pb.TagNumber(5)
+ void clearFlaky() => clearField(5);
+
+ @$pb.TagNumber(6)
+ $core.int get timeMs => $_getIZ(5);
+ @$pb.TagNumber(6)
+ set timeMs($core.int v) {
+ $_setSignedInt32(5, v);
+ }
+
+ @$pb.TagNumber(6)
+ $core.bool hasTimeMs() => $_has(5);
+ @$pb.TagNumber(6)
+ void clearTimeMs() => clearField(6);
+}
+
+class ListTestsRequest extends $pb.GeneratedMessage {
+ static final $pb.BuilderInfo _i = $pb.BuilderInfo('ListTestsRequest',
+ package: const $pb.PackageName('current_results'),
+ createEmptyInstance: create)
+ ..aOS(1, 'prefix')
+ ..a<$core.int>(2, 'limit', $pb.PbFieldType.O3)
+ ..hasRequiredFields = false;
+
+ ListTestsRequest._() : super();
+ factory ListTestsRequest() => create();
+ factory ListTestsRequest.fromBuffer($core.List<$core.int> i,
+ [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) =>
+ create()..mergeFromBuffer(i, r);
+ factory ListTestsRequest.fromJson($core.String i,
+ [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) =>
+ create()..mergeFromJson(i, r);
+ ListTestsRequest clone() => ListTestsRequest()..mergeFromMessage(this);
+ ListTestsRequest copyWith(void Function(ListTestsRequest) updates) =>
+ super.copyWith((message) => updates(message as ListTestsRequest));
+ $pb.BuilderInfo get info_ => _i;
+ @$core.pragma('dart2js:noInline')
+ static ListTestsRequest create() => ListTestsRequest._();
+ ListTestsRequest createEmptyInstance() => create();
+ static $pb.PbList<ListTestsRequest> createRepeated() =>
+ $pb.PbList<ListTestsRequest>();
+ @$core.pragma('dart2js:noInline')
+ static ListTestsRequest getDefault() => _defaultInstance ??=
+ $pb.GeneratedMessage.$_defaultFor<ListTestsRequest>(create);
+ static ListTestsRequest _defaultInstance;
+
+ @$pb.TagNumber(1)
+ $core.String get prefix => $_getSZ(0);
+ @$pb.TagNumber(1)
+ set prefix($core.String v) {
+ $_setString(0, v);
+ }
+
+ @$pb.TagNumber(1)
+ $core.bool hasPrefix() => $_has(0);
+ @$pb.TagNumber(1)
+ void clearPrefix() => clearField(1);
+
+ @$pb.TagNumber(2)
+ $core.int get limit => $_getIZ(1);
+ @$pb.TagNumber(2)
+ set limit($core.int v) {
+ $_setSignedInt32(1, v);
+ }
+
+ @$pb.TagNumber(2)
+ $core.bool hasLimit() => $_has(1);
+ @$pb.TagNumber(2)
+ void clearLimit() => clearField(2);
+}
+
+class ListTestsResponse extends $pb.GeneratedMessage {
+ static final $pb.BuilderInfo _i = $pb.BuilderInfo('ListTestsResponse',
+ package: const $pb.PackageName('current_results'),
+ createEmptyInstance: create)
+ ..pPS(1, 'names')
+ ..hasRequiredFields = false;
+
+ ListTestsResponse._() : super();
+ factory ListTestsResponse() => create();
+ factory ListTestsResponse.fromBuffer($core.List<$core.int> i,
+ [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) =>
+ create()..mergeFromBuffer(i, r);
+ factory ListTestsResponse.fromJson($core.String i,
+ [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) =>
+ create()..mergeFromJson(i, r);
+ ListTestsResponse clone() => ListTestsResponse()..mergeFromMessage(this);
+ ListTestsResponse copyWith(void Function(ListTestsResponse) updates) =>
+ super.copyWith((message) => updates(message as ListTestsResponse));
+ $pb.BuilderInfo get info_ => _i;
+ @$core.pragma('dart2js:noInline')
+ static ListTestsResponse create() => ListTestsResponse._();
+ ListTestsResponse createEmptyInstance() => create();
+ static $pb.PbList<ListTestsResponse> createRepeated() =>
+ $pb.PbList<ListTestsResponse>();
+ @$core.pragma('dart2js:noInline')
+ static ListTestsResponse getDefault() => _defaultInstance ??=
+ $pb.GeneratedMessage.$_defaultFor<ListTestsResponse>(create);
+ static ListTestsResponse _defaultInstance;
+
+ @$pb.TagNumber(1)
+ $core.List<$core.String> get names => $_getList(0);
+}
+
+class ListConfigurationsRequest extends $pb.GeneratedMessage {
+ static final $pb.BuilderInfo _i = $pb.BuilderInfo('ListConfigurationsRequest',
+ package: const $pb.PackageName('current_results'),
+ createEmptyInstance: create)
+ ..aOS(1, 'prefix')
+ ..hasRequiredFields = false;
+
+ ListConfigurationsRequest._() : super();
+ factory ListConfigurationsRequest() => create();
+ factory ListConfigurationsRequest.fromBuffer($core.List<$core.int> i,
+ [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) =>
+ create()..mergeFromBuffer(i, r);
+ factory ListConfigurationsRequest.fromJson($core.String i,
+ [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) =>
+ create()..mergeFromJson(i, r);
+ ListConfigurationsRequest clone() =>
+ ListConfigurationsRequest()..mergeFromMessage(this);
+ ListConfigurationsRequest copyWith(
+ void Function(ListConfigurationsRequest) updates) =>
+ super
+ .copyWith((message) => updates(message as ListConfigurationsRequest));
+ $pb.BuilderInfo get info_ => _i;
+ @$core.pragma('dart2js:noInline')
+ static ListConfigurationsRequest create() => ListConfigurationsRequest._();
+ ListConfigurationsRequest createEmptyInstance() => create();
+ static $pb.PbList<ListConfigurationsRequest> createRepeated() =>
+ $pb.PbList<ListConfigurationsRequest>();
+ @$core.pragma('dart2js:noInline')
+ static ListConfigurationsRequest getDefault() => _defaultInstance ??=
+ $pb.GeneratedMessage.$_defaultFor<ListConfigurationsRequest>(create);
+ static ListConfigurationsRequest _defaultInstance;
+
+ @$pb.TagNumber(1)
+ $core.String get prefix => $_getSZ(0);
+ @$pb.TagNumber(1)
+ set prefix($core.String v) {
+ $_setString(0, v);
+ }
+
+ @$pb.TagNumber(1)
+ $core.bool hasPrefix() => $_has(0);
+ @$pb.TagNumber(1)
+ void clearPrefix() => clearField(1);
+}
+
+class ListConfigurationsResponse extends $pb.GeneratedMessage {
+ static final $pb.BuilderInfo _i = $pb.BuilderInfo(
+ 'ListConfigurationsResponse',
+ package: const $pb.PackageName('current_results'),
+ createEmptyInstance: create)
+ ..pPS(1, 'configurations')
+ ..hasRequiredFields = false;
+
+ ListConfigurationsResponse._() : super();
+ factory ListConfigurationsResponse() => create();
+ factory ListConfigurationsResponse.fromBuffer($core.List<$core.int> i,
+ [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) =>
+ create()..mergeFromBuffer(i, r);
+ factory ListConfigurationsResponse.fromJson($core.String i,
+ [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) =>
+ create()..mergeFromJson(i, r);
+ ListConfigurationsResponse clone() =>
+ ListConfigurationsResponse()..mergeFromMessage(this);
+ ListConfigurationsResponse copyWith(
+ void Function(ListConfigurationsResponse) updates) =>
+ super.copyWith(
+ (message) => updates(message as ListConfigurationsResponse));
+ $pb.BuilderInfo get info_ => _i;
+ @$core.pragma('dart2js:noInline')
+ static ListConfigurationsResponse create() => ListConfigurationsResponse._();
+ ListConfigurationsResponse createEmptyInstance() => create();
+ static $pb.PbList<ListConfigurationsResponse> createRepeated() =>
+ $pb.PbList<ListConfigurationsResponse>();
+ @$core.pragma('dart2js:noInline')
+ static ListConfigurationsResponse getDefault() => _defaultInstance ??=
+ $pb.GeneratedMessage.$_defaultFor<ListConfigurationsResponse>(create);
+ static ListConfigurationsResponse _defaultInstance;
+
+ @$pb.TagNumber(1)
+ $core.List<$core.String> get configurations => $_getList(0);
+}
+
+class FetchResponse extends $pb.GeneratedMessage {
+ static final $pb.BuilderInfo _i = $pb.BuilderInfo('FetchResponse',
+ package: const $pb.PackageName('current_results'),
+ createEmptyInstance: create)
+ ..pc<ConfigurationUpdate>(1, 'updates', $pb.PbFieldType.PM,
+ subBuilder: ConfigurationUpdate.create)
+ ..hasRequiredFields = false;
+
+ FetchResponse._() : super();
+ factory FetchResponse() => create();
+ factory FetchResponse.fromBuffer($core.List<$core.int> i,
+ [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) =>
+ create()..mergeFromBuffer(i, r);
+ factory FetchResponse.fromJson($core.String i,
+ [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) =>
+ create()..mergeFromJson(i, r);
+ FetchResponse clone() => FetchResponse()..mergeFromMessage(this);
+ FetchResponse copyWith(void Function(FetchResponse) updates) =>
+ super.copyWith((message) => updates(message as FetchResponse));
+ $pb.BuilderInfo get info_ => _i;
+ @$core.pragma('dart2js:noInline')
+ static FetchResponse create() => FetchResponse._();
+ FetchResponse createEmptyInstance() => create();
+ static $pb.PbList<FetchResponse> createRepeated() =>
+ $pb.PbList<FetchResponse>();
+ @$core.pragma('dart2js:noInline')
+ static FetchResponse getDefault() => _defaultInstance ??=
+ $pb.GeneratedMessage.$_defaultFor<FetchResponse>(create);
+ static FetchResponse _defaultInstance;
+
+ @$pb.TagNumber(1)
+ $core.List<ConfigurationUpdate> get updates => $_getList(0);
+}
+
+class ConfigurationUpdate extends $pb.GeneratedMessage {
+ static final $pb.BuilderInfo _i = $pb.BuilderInfo('ConfigurationUpdate',
+ package: const $pb.PackageName('current_results'),
+ createEmptyInstance: create)
+ ..aOS(1, 'configuration')
+ ..hasRequiredFields = false;
+
+ ConfigurationUpdate._() : super();
+ factory ConfigurationUpdate() => create();
+ factory ConfigurationUpdate.fromBuffer($core.List<$core.int> i,
+ [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) =>
+ create()..mergeFromBuffer(i, r);
+ factory ConfigurationUpdate.fromJson($core.String i,
+ [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) =>
+ create()..mergeFromJson(i, r);
+ ConfigurationUpdate clone() => ConfigurationUpdate()..mergeFromMessage(this);
+ ConfigurationUpdate copyWith(void Function(ConfigurationUpdate) updates) =>
+ super.copyWith((message) => updates(message as ConfigurationUpdate));
+ $pb.BuilderInfo get info_ => _i;
+ @$core.pragma('dart2js:noInline')
+ static ConfigurationUpdate create() => ConfigurationUpdate._();
+ ConfigurationUpdate createEmptyInstance() => create();
+ static $pb.PbList<ConfigurationUpdate> createRepeated() =>
+ $pb.PbList<ConfigurationUpdate>();
+ @$core.pragma('dart2js:noInline')
+ static ConfigurationUpdate getDefault() => _defaultInstance ??=
+ $pb.GeneratedMessage.$_defaultFor<ConfigurationUpdate>(create);
+ static ConfigurationUpdate _defaultInstance;
+
+ @$pb.TagNumber(1)
+ $core.String get configuration => $_getSZ(0);
+ @$pb.TagNumber(1)
+ set configuration($core.String v) {
+ $_setString(0, v);
+ }
+
+ @$pb.TagNumber(1)
+ $core.bool hasConfiguration() => $_has(0);
+ @$pb.TagNumber(1)
+ void clearConfiguration() => clearField(1);
+}
+
+class QueryApi {
+ $pb.RpcClient _client;
+ QueryApi(this._client);
+
+ $async.Future<GetResultsResponse> getResults(
+ $pb.ClientContext ctx, GetResultsRequest request) {
+ var emptyResponse = GetResultsResponse();
+ return _client.invoke<GetResultsResponse>(
+ ctx, 'Query', 'GetResults', request, emptyResponse);
+ }
+
+ $async.Future<ListTestsResponse> listTests(
+ $pb.ClientContext ctx, ListTestsRequest request) {
+ var emptyResponse = ListTestsResponse();
+ return _client.invoke<ListTestsResponse>(
+ ctx, 'Query', 'ListTests', request, emptyResponse);
+ }
+
+ $async.Future<ListTestsResponse> listTestPathCompletions(
+ $pb.ClientContext ctx, ListTestsRequest request) {
+ var emptyResponse = ListTestsResponse();
+ return _client.invoke<ListTestsResponse>(
+ ctx, 'Query', 'ListTestPathCompletions', request, emptyResponse);
+ }
+
+ $async.Future<ListConfigurationsResponse> listConfigurations(
+ $pb.ClientContext ctx, ListConfigurationsRequest request) {
+ var emptyResponse = ListConfigurationsResponse();
+ return _client.invoke<ListConfigurationsResponse>(
+ ctx, 'Query', 'ListConfigurations', request, emptyResponse);
+ }
+
+ $async.Future<FetchResponse> fetch($pb.ClientContext ctx, $0.Empty request) {
+ var emptyResponse = FetchResponse();
+ return _client.invoke<FetchResponse>(
+ ctx, 'Query', 'Fetch', request, emptyResponse);
+ }
+}
diff --git a/ui_current_results/lib/src/generated/query.pbenum.dart b/ui_current_results/lib/src/generated/query.pbenum.dart
new file mode 100644
index 0000000..277e345
--- /dev/null
+++ b/ui_current_results/lib/src/generated/query.pbenum.dart
@@ -0,0 +1,6 @@
+///
+// Generated code. Do not modify.
+// source: query.proto
+//
+// @dart = 2.3
+// ignore_for_file: camel_case_types,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name,return_of_invalid_type
diff --git a/ui_current_results/lib/src/generated/query.pbjson.dart b/ui_current_results/lib/src/generated/query.pbjson.dart
new file mode 100644
index 0000000..9e4ee01
--- /dev/null
+++ b/ui_current_results/lib/src/generated/query.pbjson.dart
@@ -0,0 +1,158 @@
+///
+// Generated code. Do not modify.
+// source: query.proto
+//
+// @dart = 2.3
+// ignore_for_file: camel_case_types,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name,return_of_invalid_type
+
+import 'google/protobuf/empty.pbjson.dart' as $0;
+
+const GetResultsRequest$json = const {
+ '1': 'GetResultsRequest',
+ '2': const [
+ const {'1': 'names', '3': 1, '4': 3, '5': 9, '10': 'names'},
+ const {
+ '1': 'configurations',
+ '3': 2,
+ '4': 3,
+ '5': 9,
+ '10': 'configurations'
+ },
+ const {'1': 'page_size', '3': 3, '4': 1, '5': 5, '10': 'pageSize'},
+ const {'1': 'page_token', '3': 4, '4': 1, '5': 9, '10': 'pageToken'},
+ ],
+};
+
+const GetResultsResponse$json = const {
+ '1': 'GetResultsResponse',
+ '2': const [
+ const {
+ '1': 'results',
+ '3': 1,
+ '4': 3,
+ '5': 11,
+ '6': '.current_results.Result',
+ '10': 'results'
+ },
+ const {
+ '1': 'next_page_token',
+ '3': 2,
+ '4': 1,
+ '5': 9,
+ '10': 'nextPageToken'
+ },
+ ],
+};
+
+const Result$json = const {
+ '1': 'Result',
+ '2': const [
+ const {'1': 'name', '3': 1, '4': 1, '5': 9, '10': 'name'},
+ const {'1': 'configuration', '3': 2, '4': 1, '5': 9, '10': 'configuration'},
+ const {'1': 'result', '3': 3, '4': 1, '5': 9, '10': 'result'},
+ const {'1': 'expected', '3': 4, '4': 1, '5': 9, '10': 'expected'},
+ const {'1': 'flaky', '3': 5, '4': 1, '5': 8, '10': 'flaky'},
+ const {'1': 'time_ms', '3': 6, '4': 1, '5': 5, '10': 'timeMs'},
+ ],
+};
+
+const ListTestsRequest$json = const {
+ '1': 'ListTestsRequest',
+ '2': const [
+ const {'1': 'prefix', '3': 1, '4': 1, '5': 9, '10': 'prefix'},
+ const {'1': 'limit', '3': 2, '4': 1, '5': 5, '10': 'limit'},
+ ],
+};
+
+const ListTestsResponse$json = const {
+ '1': 'ListTestsResponse',
+ '2': const [
+ const {'1': 'names', '3': 1, '4': 3, '5': 9, '10': 'names'},
+ ],
+};
+
+const ListConfigurationsRequest$json = const {
+ '1': 'ListConfigurationsRequest',
+ '2': const [
+ const {'1': 'prefix', '3': 1, '4': 1, '5': 9, '10': 'prefix'},
+ ],
+};
+
+const ListConfigurationsResponse$json = const {
+ '1': 'ListConfigurationsResponse',
+ '2': const [
+ const {
+ '1': 'configurations',
+ '3': 1,
+ '4': 3,
+ '5': 9,
+ '10': 'configurations'
+ },
+ ],
+};
+
+const FetchResponse$json = const {
+ '1': 'FetchResponse',
+ '2': const [
+ const {
+ '1': 'updates',
+ '3': 1,
+ '4': 3,
+ '5': 11,
+ '6': '.current_results.ConfigurationUpdate',
+ '10': 'updates'
+ },
+ ],
+};
+
+const ConfigurationUpdate$json = const {
+ '1': 'ConfigurationUpdate',
+ '2': const [
+ const {'1': 'configuration', '3': 1, '4': 1, '5': 9, '10': 'configuration'},
+ ],
+};
+
+const QueryServiceBase$json = const {
+ '1': 'Query',
+ '2': const [
+ const {
+ '1': 'GetResults',
+ '2': '.current_results.GetResultsRequest',
+ '3': '.current_results.GetResultsResponse'
+ },
+ const {
+ '1': 'ListTests',
+ '2': '.current_results.ListTestsRequest',
+ '3': '.current_results.ListTestsResponse'
+ },
+ const {
+ '1': 'ListTestPathCompletions',
+ '2': '.current_results.ListTestsRequest',
+ '3': '.current_results.ListTestsResponse'
+ },
+ const {
+ '1': 'ListConfigurations',
+ '2': '.current_results.ListConfigurationsRequest',
+ '3': '.current_results.ListConfigurationsResponse'
+ },
+ const {
+ '1': 'Fetch',
+ '2': '.google.protobuf.Empty',
+ '3': '.current_results.FetchResponse'
+ },
+ ],
+};
+
+const QueryServiceBase$messageJson = const {
+ '.current_results.GetResultsRequest': GetResultsRequest$json,
+ '.current_results.GetResultsResponse': GetResultsResponse$json,
+ '.current_results.Result': Result$json,
+ '.current_results.ListTestsRequest': ListTestsRequest$json,
+ '.current_results.ListTestsResponse': ListTestsResponse$json,
+ '.current_results.ListConfigurationsRequest': ListConfigurationsRequest$json,
+ '.current_results.ListConfigurationsResponse':
+ ListConfigurationsResponse$json,
+ '.google.protobuf.Empty': $0.Empty$json,
+ '.current_results.FetchResponse': FetchResponse$json,
+ '.current_results.ConfigurationUpdate': ConfigurationUpdate$json,
+};
diff --git a/ui_current_results/lib/src/generated/query.pbserver.dart b/ui_current_results/lib/src/generated/query.pbserver.dart
new file mode 100644
index 0000000..ab2b362
--- /dev/null
+++ b/ui_current_results/lib/src/generated/query.pbserver.dart
@@ -0,0 +1,69 @@
+///
+// Generated code. Do not modify.
+// source: query.proto
+//
+// @dart = 2.3
+// ignore_for_file: camel_case_types,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name,return_of_invalid_type
+
+import 'dart:async' as $async;
+
+import 'package:protobuf/protobuf.dart' as $pb;
+
+import 'dart:core' as $core;
+import 'query.pb.dart' as $1;
+import 'google/protobuf/empty.pb.dart' as $0;
+import 'query.pbjson.dart';
+
+export 'query.pb.dart';
+
+abstract class QueryServiceBase extends $pb.GeneratedService {
+ $async.Future<$1.GetResultsResponse> getResults(
+ $pb.ServerContext ctx, $1.GetResultsRequest request);
+ $async.Future<$1.ListTestsResponse> listTests(
+ $pb.ServerContext ctx, $1.ListTestsRequest request);
+ $async.Future<$1.ListTestsResponse> listTestPathCompletions(
+ $pb.ServerContext ctx, $1.ListTestsRequest request);
+ $async.Future<$1.ListConfigurationsResponse> listConfigurations(
+ $pb.ServerContext ctx, $1.ListConfigurationsRequest request);
+ $async.Future<$1.FetchResponse> fetch(
+ $pb.ServerContext ctx, $0.Empty request);
+
+ $pb.GeneratedMessage createRequest($core.String method) {
+ switch (method) {
+ case 'GetResults':
+ return $1.GetResultsRequest();
+ case 'ListTests':
+ return $1.ListTestsRequest();
+ case 'ListTestPathCompletions':
+ return $1.ListTestsRequest();
+ case 'ListConfigurations':
+ return $1.ListConfigurationsRequest();
+ case 'Fetch':
+ return $0.Empty();
+ default:
+ throw $core.ArgumentError('Unknown method: $method');
+ }
+ }
+
+ $async.Future<$pb.GeneratedMessage> handleCall($pb.ServerContext ctx,
+ $core.String method, $pb.GeneratedMessage request) {
+ switch (method) {
+ case 'GetResults':
+ return this.getResults(ctx, request);
+ case 'ListTests':
+ return this.listTests(ctx, request);
+ case 'ListTestPathCompletions':
+ return this.listTestPathCompletions(ctx, request);
+ case 'ListConfigurations':
+ return this.listConfigurations(ctx, request);
+ case 'Fetch':
+ return this.fetch(ctx, request);
+ default:
+ throw $core.ArgumentError('Unknown method: $method');
+ }
+ }
+
+ $core.Map<$core.String, $core.dynamic> get $json => QueryServiceBase$json;
+ $core.Map<$core.String, $core.Map<$core.String, $core.dynamic>>
+ get $messageJson => QueryServiceBase$messageJson;
+}