oto/apps/runner/test/oto_agent_migration_plan_test.dart
toki 7daa0d77d7 feat(control-plane): runner 온라인 상태를 연결한다
Dart runner와 Go OTO Core가 등록 이후 heartbeat/disconnect 상태를 공유하도록 한다.

마이그레이션 smoke 근거를 실제 OTO Server 검증으로 고정한다.
2026-06-05 16:21:58 +09:00

164 lines
5.3 KiB
Dart

import 'package:test/test.dart';
class SmokeFixtureBoundary {
final String name;
final String target;
final bool startsExternalRepo;
final List<String> requiredInputs;
final List<String> expectedEvidence;
final List<String> forbiddenDependencies;
const SmokeFixtureBoundary({
required this.name,
required this.target,
required this.startsExternalRepo,
required this.requiredInputs,
required this.expectedEvidence,
required this.forbiddenDependencies,
});
}
class SmokeMigrationStep {
final String id;
final String description;
const SmokeMigrationStep(this.id, this.description);
}
class OtoServerSmokeMigrationPlan {
final SmokeFixtureBoundary legacySource;
final SmokeFixtureBoundary otoServerTarget;
final List<SmokeMigrationStep> steps;
const OtoServerSmokeMigrationPlan({
required this.legacySource,
required this.otoServerTarget,
required this.steps,
});
}
const migrationPlan = OtoServerSmokeMigrationPlan(
legacySource: SmokeFixtureBoundary(
name: 'legacy-iop-edge-online-smoke',
target: 'apps/runner/test/oto_iop_connection_smoke_test.dart',
startsExternalRepo: true,
requiredInputs: [
'IOP_REPO_ROOT or workspace sibling iop checkout',
'iop Edge config fixture',
'iop runtime RegisterRequest/RegisterResponse protobuf',
],
expectedEvidence: [
'registration accepted by iop Edge',
'first heartbeat transitions the iop Edge node record to online',
],
forbiddenDependencies: [],
),
otoServerTarget: SmokeFixtureBoundary(
name: 'oto-server-runner-online-smoke',
target: 'apps/runner/test/oto_server_connection_smoke_test.dart',
startsExternalRepo: false,
requiredInputs: [
'loopback OTO Core listener with dynamic port',
'temporary runner install/workspace/log directories',
'runner enrollment token fixture owned by services/core',
'OTO Server registration and heartbeat contract fixture',
],
expectedEvidence: [
'runner registration accepted by OTO Server',
'runner id and alias recorded in OTO Server registry',
'first heartbeat or equivalent online signal marks runner online',
],
forbiddenDependencies: [
'IOP_REPO_ROOT',
'../iop checkout',
'iop Edge process',
'iop runtime protobuf as the acceptance contract',
],
),
steps: [
SmokeMigrationStep(
'freeze-legacy',
'Keep the iop smoke as migration source evidence until the OTO Server '
'target fixture reaches parity.',
),
SmokeMigrationStep(
'define-core-fixture',
'Add a services/core test fixture that can issue enrollment tokens, '
'accept runner registration, and expose runner online state.',
),
SmokeMigrationStep(
'define-runner-fixture',
'Start OTO Core on loopback from the runner test, create temporary '
'runtime directories, and point AgentConfig at the OTO Server target.',
),
SmokeMigrationStep(
'replace-contract',
'Replace iop RegisterRequest/RegisterResponse acceptance with an OTO '
'Server owned registration and heartbeat contract.',
),
SmokeMigrationStep(
'retire-iop-smoke',
'Remove the iop smoke from required acceptance once the OTO Server smoke '
'proves registration accepted and online evidence.',
),
],
);
void main() {
group('OTO Server migration smoke plan', () {
test('keeps the existing iop smoke as legacy source evidence only', () {
expect(migrationPlan.legacySource.name, 'legacy-iop-edge-online-smoke');
expect(migrationPlan.legacySource.startsExternalRepo, isTrue);
expect(
migrationPlan.legacySource.requiredInputs,
contains('IOP_REPO_ROOT or workspace sibling iop checkout'),
);
expect(
migrationPlan.legacySource.expectedEvidence,
contains('registration accepted by iop Edge'),
);
});
test('defines an OTO Server target fixture without iop dependencies', () {
final target = migrationPlan.otoServerTarget;
expect(target.name, 'oto-server-runner-online-smoke');
expect(target.startsExternalRepo, isFalse);
expect(
target.requiredInputs,
contains('loopback OTO Core listener with dynamic port'),
);
expect(
target.requiredInputs,
contains('runner enrollment token fixture owned by services/core'),
);
expect(
target.expectedEvidence,
contains('runner registration accepted by OTO Server'),
);
expect(target.forbiddenDependencies, contains('IOP_REPO_ROOT'));
expect(target.forbiddenDependencies, contains('../iop checkout'));
expect(target.forbiddenDependencies, contains('iop Edge process'));
expect(
target.forbiddenDependencies,
contains('iop runtime protobuf as the acceptance contract'),
);
});
test('orders the handoff before retiring the iop smoke', () {
final stepIds = migrationPlan.steps.map((step) => step.id).toList();
expect(stepIds, [
'freeze-legacy',
'define-core-fixture',
'define-runner-fixture',
'replace-contract',
'retire-iop-smoke',
]);
expect(
migrationPlan.steps.last.description,
contains('Remove the iop smoke from required acceptance'),
);
});
});
}