Skip to content

Commit

Permalink
Update file being read by the GUI
Browse files Browse the repository at this point in the history
The GUI must now read from the home directory. There was some complexity
in disinguishing LocalAppData from AppData that has now become simpler,
and related tests are no longer necessary.
  • Loading branch information
EduardGomezEscandell committed Nov 8, 2023
1 parent 1d03b8c commit 57a229e
Show file tree
Hide file tree
Showing 12 changed files with 53 additions and 106 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -27,22 +27,28 @@ void main() {
return stack;
};

// A temporary directory mocking the $env:LocalAppData directory to sandbox our agent.
Directory? tmp;
// A temporary directory mocking the $env:UserProfile directory to sandbox our agent.
Directory? tmpHome;
Directory? tmpLocalAppData;

setUpAll(() async {
await YaruTestWindow.ensureInitialized();
// Use a random place inside the build tree as the `LOCALAPPDATA` env variable for all test cases below.
tmp = await msixRootDir().createTemp('test-');
// Use a random place inside the build tree as the `USERPROFILE` env variable for all test cases below.
tmpHome = await msixRootDir().createTemp('test-');

tmpLocalAppData = Directory(p.join(tmpHome!.path, 'AppData/Local'));
await tmpLocalAppData!.create(recursive: true);

Environment(
overrides: {
'LOCALAPPDATA': tmp!.path,
'USERPROFILE': tmpHome!.path,
'LOCALAPPDATA': tmpLocalAppData!.path,
'UP4W_ALLOW_STORE_PURCHASE': '1',
},
);
});

tearDownAll(() => tmp?.delete(recursive: true));
tearDownAll(() => tmpHome?.delete(recursive: true));
group('no agent build', () {
// Verifies that a proper message is displayed when the agent cannot be run.
testWidgets(
Expand Down Expand Up @@ -82,7 +88,7 @@ void main() {
[p.basenameWithoutExtension(agentImageName)],
);
}
File(p.join(tmp!.path, 'Ubuntu Pro', 'addr')).deleteSync();
File(p.join(tmpHome!.path, 'Ubuntu Pro', '.ubuntupro')).deleteSync();
});

tearDownAll(() async {
Expand Down
3 changes: 1 addition & 2 deletions gui/packages/ubuntupro/lib/app.dart
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ class Pro4WindowsApp extends StatelessWidget {
builder: (context, yaru, child) => ChangeNotifierProvider(
create: (_) => ValueNotifier(SubscriptionInfo()),
child: MaterialApp(
title: kAppName,
title: 'Ubuntu Pro',
theme: yaru.theme,
darkTheme: yaru.darkTheme,
debugShowCheckedModeBanner: false,
Expand All @@ -32,7 +32,6 @@ class Pro4WindowsApp extends StatelessWidget {
onGenerateTitle: (context) => AppLocalizations.of(context).appTitle,
home: Provider<AgentStartupMonitor>(
create: (context) => AgentStartupMonitor(
appName: kAppName,
addrFileName: kAddrFileName,
agentLauncher: launch,
clientFactory: defaultClient,
Expand Down
5 changes: 1 addition & 4 deletions gui/packages/ubuntupro/lib/constants.dart
Original file line number Diff line number Diff line change
@@ -1,11 +1,8 @@
/// The address where the Agent gRPC service is hosted.
const kDefaultHost = '127.0.0.1';

/// This app's name. Needed to find the Agent's addr file.
const kAppName = 'Ubuntu Pro';

/// The name of the file where the Agent's drop its service connection information.
const kAddrFileName = 'addr';
const kAddrFileName = '.ubuntupro';

/// The default border margin.
const kDefaultMargin = 32.0;
Expand Down
16 changes: 4 additions & 12 deletions gui/packages/ubuntupro/lib/core/agent_api_paths.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,21 +5,13 @@ import 'package:path/path.dart' as p;

import 'environment.dart';

/// Provides the full path of the "[appDir]/[filename]" file
/// Provides the full path of the "[filename]" file
/// under the well known directory where the Windows Agent stores its local data.
/// Returns null if that directory location cannot be determined from the environment.
String? agentAddrFilePath(String appDir, String filename) {
// The well-known package path_provider doesn't return the LOCALAPPDATA directory
// but the APPDATA, which is usually under %USERPROFILE%/AppData/Roaming instead of
// %USERPROFILE%/AppData/Local, which is where the agent is storing the support data.
final localAppDir = Environment.instance['LOCALAPPDATA'];
String? agentAddrFilePath(String filename) {
final localAppDir = Environment.instance['USERPROFILE'];
if (localAppDir != null) {
return p.join(localAppDir, appDir, filename);
}

final userProfile = Environment.instance['USERPROFILE'];
if (userProfile != null) {
return p.join(userProfile, 'AppData', 'Local', appDir, filename);
return p.join(localAppDir, filename);
}

return null;
Expand Down
11 changes: 5 additions & 6 deletions gui/packages/ubuntupro/lib/pages/startup/agent_monitor.dart
Original file line number Diff line number Diff line change
Expand Up @@ -49,12 +49,11 @@ typedef AgentApiCallback = FutureOr<void> Function(AgentApiClient);

class AgentStartupMonitor {
AgentStartupMonitor({
required String appName,
required String addrFileName,
required this.agentLauncher,
required this.clientFactory,
required this.onClient,
}) : _addrFilePath = agentAddrFilePath(appName, addrFileName);
}) : _addrFilePath = agentAddrFilePath(addrFileName);

final String? _addrFilePath;

Expand All @@ -68,9 +67,9 @@ class AgentStartupMonitor {
final AgentApiCallback onClient;

/// Models the background agent as seen by the GUI as a state machine, i.e.:
/// 1. Agent running state is checked (by looking for the `addr` file).
/// 1. Agent running state is checked (by looking for the `.ubuntpro` file).
/// 2. Agent start is requested by calling [agentLaucher] if not running.
/// 3. Contents of the `addr` file are scanned periodically (between [interval]).
/// 3. Contents of the `.ubuntpro` file are scanned periodically (between [interval]).
/// 4. When a port is available, [clientFactory] is called to create a new
/// [AgentApiClient].
/// 5. When a PING request succeeds, the [onClient] function is called with
Expand Down Expand Up @@ -156,9 +155,9 @@ class AgentStartupMonitor {
return AgentState.pingNonResponsive;
}

/// Assumes the agent crashed, i.e. the `addr` file exists but the agent
/// Assumes the agent crashed, i.e. the `.ubuntupro` file exists but the agent
/// cannot respond to PING requets.
/// Thus, we delete the existing `addr` file and retry launching the agent.
/// Thus, we delete the existing `.ubuntupro` file and retry launching the agent.
Future<void> reset() async {
if (_addrFilePath != null) {
try {
Expand Down
4 changes: 2 additions & 2 deletions gui/packages/ubuntupro/lib/pages/startup/startup_model.dart
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,8 @@ class StartupModel extends ChangeNotifier {
return completer.future;
}

/// Assumes the agent crashed, i.e. the `addr` file exists but the agent cannot respond to PING requets.
/// Thus, we delete the existing `addr` file and try launching the agent.
/// Assumes the agent crashed, i.e. the `.ubuntupro` file exists but the agent cannot respond to PING requets.
/// Thus, we delete the existing `.ubuntupro` file and try launching the agent.
Future<void> resetAgent() async {
assert(
_view == ViewState.retry,
Expand Down
14 changes: 3 additions & 11 deletions gui/packages/ubuntupro/test/core/agent_api_paths_part2_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
import 'dart:io';

import 'package:flutter_test/flutter_test.dart';
import 'package:ubuntupro/core/agent_api_paths.dart';
import 'package:ubuntupro/core/environment.dart';

void main() {
Expand All @@ -15,15 +14,8 @@ void main() {
// that will cost only a branch on if-null. Maybe the compiler can optimize
// that away. I'm not sure.
final _ = Environment(
overrides: {'LOCALAPPDATA': Platform.environment['APPDATA']!},
overrides: {
'USERPROFILE': Platform.environment['USERPROFILE']!,
},
);

test('misleading environment', () {
const appName = 'AwesomeApp';

final dir = agentAddrFilePath(appName, 'addr')!;

expect(dir.contains('Roaming'), isTrue);
expect(dir.contains(appName), isTrue);
});
}
22 changes: 0 additions & 22 deletions gui/packages/ubuntupro/test/core/agent_api_paths_part3_test.dart

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,7 @@ void main() {
final _ = Environment(overrides: {'LOCALAPPDATA': null, 'USERPROFILE': null});

test('complete failure due environment', () {
const appName = 'AwesomeApp';

final dir = agentAddrFilePath(appName, 'addr');
final dir = agentAddrFilePath('.ubuntupro');

expect(dir, isNull);
});
Expand Down
19 changes: 5 additions & 14 deletions gui/packages/ubuntupro/test/core/agent_api_paths_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,7 @@ import 'package:flutter_test/flutter_test.dart';
import 'package:ubuntupro/core/agent_api_paths.dart';

void main() {
tearDownAll(() => File('./addr').deleteSync());
test('dir should not contain "Roaming"', () {
const appName = 'AwesomeApp';

final dir = agentAddrFilePath(appName, 'addr')!;

expect(dir.contains('Roaming'), isFalse);
expect(dir.contains('Local'), isTrue);
expect(dir.contains(appName), isTrue);
});
tearDownAll(() => File('./.ubuntupro').deleteSync());

test('read port from line', () {
const port = 56768;
Expand All @@ -37,7 +28,7 @@ void main() {
});

test('read port from addr file', () async {
const filePath = './addr';
const filePath = './.ubuntupro';
const port = 56768;
const line = '[::]:$port';
final addr = File(filePath);
Expand All @@ -59,7 +50,7 @@ void main() {
});

test('empty file', () async {
const filePath = './addr';
const filePath = './.ubuntupro';
final addr = File(filePath);
addr.writeAsStringSync('');

Expand All @@ -70,7 +61,7 @@ void main() {
});

test('access denied', () async {
const filePath = './addr';
const filePath = './.ubuntupro';
final addr = File(filePath);
addr.writeAsStringSync('');

Expand All @@ -86,7 +77,7 @@ void main() {
});

test('bad format', () async {
const filePath = './addr';
const filePath = './.ubuntupro';
const port = 56768;
const line = 'Hello World $port';
final addr = File(filePath);
Expand Down
Loading

0 comments on commit 57a229e

Please sign in to comment.