Files
2026-10-11 07:21:11 -04:00

69 lines
1.7 KiB
C++

#pragma once
#include <filesystem>
#include <optional>
#include <ostream>
#include <string>
#include <vector>
namespace ota {
enum class Phase {
AConfirmed, PreparingB, BPrepared, TrialPending, TrialRunning,
BConfirmed, RecoveryPending, RecoveryRunning, RecoveryChecked,
SeparateRecoveryRequired
};
enum class Slot { A, B };
const char* name(Phase phase);
const char* name(Slot slot);
struct State {
Phase phase = Phase::AConfirmed;
Slot normal = Slot::A;
std::optional<Slot> trial;
int attempts_left = 0;
bool a_ready = true;
bool b_ready = false;
std::string outcome;
};
class Device {
public:
explicit Device(const std::filesystem::path& directory);
const State& state() const { return state_; }
std::optional<Slot> running() const { return running_; }
void prepare(bool complete = true);
void request_trial(int attempts = 2);
Slot boot();
void check(bool healthy);
private:
void save() const;
State state_;
std::filesystem::path path_;
// Volatile: reconstructing a Device requires another boot before checks.
std::optional<Slot> running_;
};
// Own only a freshly created directory and clean it up at scope exit.
class TemporaryDirectory {
public:
TemporaryDirectory();
~TemporaryDirectory();
TemporaryDirectory(const TemporaryDirectory&) = delete;
TemporaryDirectory& operator=(const TemporaryDirectory&) = delete;
const std::filesystem::path& path() const { return path_; }
private:
std::filesystem::path path_;
};
const std::vector<std::string>& scenarios();
Device run_scenario(const std::string& scenario,
const std::filesystem::path& directory,
std::ostream* output = nullptr);
} // namespace ota