69 lines
1.7 KiB
C++
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
|