Skip to content

Commit

Permalink
test: Dart and Local SshKeyHandler tests
Browse files Browse the repository at this point in the history
  • Loading branch information
XavierChanth committed Nov 21, 2023
1 parent 7f732e3 commit 5b4fe9f
Show file tree
Hide file tree
Showing 5 changed files with 196 additions and 7 deletions.
4 changes: 2 additions & 2 deletions packages/noports_core/test/sshnp/sshnp_core_mocks.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ import 'sshnp_core_constants.dart';

/// Mocked Classes
/// Stubbed [SshnpCore] (minimum viable implementation of [SshnpCore])
class StubbedSshnpCore extends SshnpCore with StubbedAsyncInitializationMixin {
StubbedSshnpCore({
class StubbedSshnp extends SshnpCore with StubbedAsyncInitializationMixin {
StubbedSshnp({
required super.atClient,
required super.params,
SshnpdChannel? sshnpdChannel,
Expand Down
10 changes: 5 additions & 5 deletions packages/noports_core/test/sshnp/sshnp_core_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ void main() {
stubbedCompleteInitialization = FunctionStub();
});

/// When declaration setup for the constructor of [StubbedSshnpCore]
/// When declaration setup for the constructor of [StubbedSshnp]
whenConstructor({bool verbose = false}) {
when(() => mockParams.device).thenReturn('mydevice');
when(() => mockParams.localPort).thenReturn(0);
Expand All @@ -44,7 +44,7 @@ void main() {
when(() => mockAtClient.setPreferences(any())).thenReturn(null);
}

/// When declaration setup for the initialization of [StubbedSshnpCore]
/// When declaration setup for the initialization of [StubbedSshnp]
whenInitialization({AtSshKeyPair? identityKeyPair}) {
when(() => stubbedCallInitialization()).thenAnswer((_) async {});
when(() => stubbedInitialize()).thenAnswer((_) async {});
Expand All @@ -65,7 +65,7 @@ void main() {
whenConstructor(verbose: false);

final sshnpCore =
StubbedSshnpCore(atClient: mockAtClient, params: mockParams);
StubbedSshnp(atClient: mockAtClient, params: mockParams);

/// Expect that the namespace is set in the preferences
verify(() => mockAtClient.getPreferences()).called(1);
Expand All @@ -81,7 +81,7 @@ void main() {
whenConstructor(verbose: true);

final sshnpCore =
StubbedSshnpCore(atClient: mockAtClient, params: mockParams);
StubbedSshnp(atClient: mockAtClient, params: mockParams);

/// Expect that the namespace is set in the preferences
verify(() => mockAtClient.getPreferences()).called(1);
Expand All @@ -99,7 +99,7 @@ void main() {
test('AsyncInitialization', () async {
whenConstructor();

final sshnpCore = StubbedSshnpCore(
final sshnpCore = StubbedSshnp(
atClient: mockAtClient,
params: mockParams,
sshnpdChannel: mockSshnpdChannel,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import 'package:noports_core/sshnp_foundation.dart';
import 'package:test/test.dart';

import 'sshnp_ssh_key_handler_mocks.dart';

void main() {
group('SshnpDartSshKeyHandler', () {
late MockSshnpDartSshKeyHandler keyHandler;
late MockAtSshKeyPair mockKeyPair;

setUp(() {
keyHandler = MockSshnpDartSshKeyHandler();
mockKeyPair = MockAtSshKeyPair();
});

test('public API', () {
/// The Dart key handler requires that there is a setter for
/// identityKeyPair, in addition to a getter
keyHandler.identityKeyPair = mockKeyPair;
expect(keyHandler.identityKeyPair, mockKeyPair);

expect(MockSshnpDartSshKeyHandler(), isA<SshnpKeyHandler>());
}); // test initialization
}); // group SshnpDartKeyHandler
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
import 'package:at_client/at_client.dart';
import 'package:noports_core/sshnp_foundation.dart';
import 'package:test/test.dart';
import 'package:mocktail/mocktail.dart';

import '../../sshnp_mocks.dart';
import 'sshnp_ssh_key_handler_mocks.dart';

void main() {
group('SshnpLocalSshKeyHandler', () {
late MockAtClient mockAtClient;
late MockSshnpParams mockParams;
late MockLocalSshKeyUtil keyUtil;
late MockAtSshKeyPair keyPair;

late MockSshnpdChannel mockSshnpdChannel;
late MockSshrvdChannel mockSshrvdChannel;

setUp(() {
mockAtClient = MockAtClient();
mockParams = MockSshnpParams();
keyUtil = MockLocalSshKeyUtil();
keyPair = MockAtSshKeyPair();

mockSshnpdChannel = MockSshnpdChannel();
mockSshrvdChannel = MockSshrvdChannel();
registerFallbackValue(AtClientPreference());
});

whenConstructor() {
when(() => mockParams.device).thenReturn('mydevice');
when(() => mockParams.localPort).thenReturn(0);
when(() => mockParams.verbose).thenReturn(false);
when(() => mockAtClient.getPreferences()).thenReturn(null);
when(() => mockAtClient.setPreferences(any())).thenReturn(null);
}

whenInitialization({AtSshKeyPair? identityKeyPair}) {
when(() => mockSshnpdChannel.callInitialization())
.thenAnswer((_) async {});
when(() => mockSshnpdChannel.resolveRemoteUsername())
.thenAnswer((_) async => 'myRemoteUsername');
when(() => mockSshnpdChannel.sharePublicKeyIfRequired(identityKeyPair))
.thenAnswer((_) async {});
when(() => mockSshrvdChannel.callInitialization())
.thenAnswer((_) async {});
}

test('public API', () {
whenConstructor();
final sshnp = StubbedSshnp(
atClient: mockAtClient,
params: mockParams,
);
expect(sshnp, isA<SshnpKeyHandler>());
}); // test public API

test('initialization', () async {
whenConstructor();

final sshnp = StubbedSshnp(
atClient: mockAtClient,
params: mockParams,
sshKeyUtil: keyUtil,
sshnpdChannel: mockSshnpdChannel,
sshrvdChannel: mockSshrvdChannel,
);

whenInitialization(identityKeyPair: keyPair);
final identityFile = '.ssh/asdf';
when(() => keyUtil.isValidPlatform).thenReturn(true);
when(() => mockParams.identityFile).thenReturn(identityFile);
when(() => keyUtil.getKeyPair(identifier: identityFile))
.thenAnswer((_) async => keyPair);

/// normally we would call [callInitialization()] but it's fine to call
/// initialize directly for testing purposes, since we avoid weird
/// lifecycle issues that could be caused by mocking
await sshnp.initialize();

/// We don't care about [SshnpCore] initialization here, we only care that
/// the [keyPair] is set correctly, since [SshnpCore] is tested elsewhere
expect(sshnp.identityKeyPair, keyPair);
}); // test initialization

test('initialization - no identityFile', () async {
whenConstructor();

final sshnp = StubbedSshnp(
atClient: mockAtClient,
params: mockParams,
sshKeyUtil: keyUtil,
sshnpdChannel: mockSshnpdChannel,
sshrvdChannel: mockSshrvdChannel,
);

whenInitialization(identityKeyPair: keyPair);
when(() => keyUtil.isValidPlatform).thenReturn(true);
when(() => mockParams.identityFile).thenReturn(null);
when(() => mockSshnpdChannel.sharePublicKeyIfRequired(null))
.thenAnswer((_) async {});
when(() => keyUtil.getKeyPair(identifier: '.ssh/asdf'))
.thenAnswer((_) async => keyPair);

/// normally we would call [callInitialization()] but it's fine to call
/// initialize directly for testing purposes, since we avoid weird
/// lifecycle issues that could be caused by mocking
await sshnp.initialize();

/// We don't care about [SshnpCore] initialization here, we only care that
/// the [keyPair] is set correctly, since [SshnpCore] is tested elsewhere
expect(sshnp.identityKeyPair, null);
}); // test initialization - no identityFile

test('initialization - invalid platform', () {
whenConstructor();

final sshnp = StubbedSshnp(
atClient: mockAtClient,
params: mockParams,
sshKeyUtil: keyUtil,
sshnpdChannel: mockSshnpdChannel,
sshrvdChannel: mockSshrvdChannel,
);

whenInitialization();
when(() => keyUtil.isValidPlatform).thenReturn(false);
expect(sshnp.initialize(), throwsA(isA<SshnpError>()));
});
}); // group SshnpLocalSshKeyHandler
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,36 @@ class MockSshnpKeyHandler extends Mock with SshnpKeyHandler {}
class MockAtSshKeyUtil extends Mock implements AtSshKeyUtil {}

class MockAtSshKeyPair extends Mock implements AtSshKeyPair {}

class MockSshnpDartSshKeyHandler extends Mock with SshnpDartSshKeyHandler {}

class StubbedSshnp extends SshnpCore with SshnpLocalSshKeyHandler {
@override
LocalSshKeyUtil get keyUtil => _sshKeyUtil ?? (throw UnimplementedError());
final LocalSshKeyUtil? _sshKeyUtil;

StubbedSshnp({
required super.atClient,
required super.params,
LocalSshKeyUtil? sshKeyUtil,
SshnpdChannel? sshnpdChannel,
SshrvdChannel? sshrvdChannel,
}) : _sshKeyUtil = sshKeyUtil,
_sshnpdChannel = sshnpdChannel,
_sshrvdChannel = sshrvdChannel;

@override
Future<SshnpResult> run() => throw UnimplementedError();

@override
SshnpdChannel get sshnpdChannel =>
_sshnpdChannel ?? (throw UnimplementedError());
final SshnpdChannel? _sshnpdChannel;

@override
SshrvdChannel get sshrvdChannel =>
_sshrvdChannel ?? (throw UnimplementedError());
final SshrvdChannel? _sshrvdChannel;
}

class MockLocalSshKeyUtil extends Mock implements LocalSshKeyUtil {}

0 comments on commit 5b4fe9f

Please sign in to comment.