5#include "absl/strings/ascii.h"
6#include "absl/strings/str_cat.h"
7#include "absl/strings/str_format.h"
8#include "absl/time/clock.h"
9#include "absl/time/time.h"
20#if defined(YAZE_WITH_GRPC)
21const char* HarnessStatusToString(test::HarnessTestStatus status) {
23 case HarnessTestStatus::kQueued:
25 case HarnessTestStatus::kRunning:
27 case HarnessTestStatus::kPassed:
29 case HarnessTestStatus::kFailed:
31 case HarnessTestStatus::kTimeout:
33 case HarnessTestStatus::kUnspecified:
44 : recorder_(recorder), active_(active) {}
47 if (!recorder_ || !active_) {
50 absl::MutexLock lock(&recorder_->mu_);
51 recorder_->suspended_ =
false;
59 absl::MutexLock lock(&
mu_);
64 const std::string& recording_id,
bool discard) {
65 absl::MutexLock lock(&
mu_);
70 absl::MutexLock lock(&
mu_);
75 absl::MutexLock lock(&
mu_);
76 return recording_ && !suspended_;
80 absl::MutexLock lock(&
mu_);
85 absl::MutexLock lock(&
mu_);
86 bool activate =
false;
97 return absl::FailedPreconditionError(
98 "A recording session is already active");
101 return absl::FailedPreconditionError(
"TestManager unavailable");
104 return absl::InvalidArgumentError(
105 "Recording requires a non-empty output path");
111 if (options_.session_name.empty()) {
114 started_at_ = absl::Now();
117 return recording_id_;
121 const std::string& recording_id,
bool discard) {
123 return absl::FailedPreconditionError(
"No active recording session");
125 if (!recording_id.empty() && recording_id != recording_id_) {
126 return absl::InvalidArgumentError(
127 absl::StrFormat(
"Recording ID mismatch (expected %s)", recording_id_));
131 summary.
step_count =
static_cast<int>(steps_.size());
132 summary.
duration = absl::Now() - started_at_;
134 summary.
saved = !discard;
140 script.
name = options_.session_name;
145 for (
const auto& step : steps_) {
148 script_step.
target = step.target;
149 script_step.
click_type = absl::AsciiStrToLower(step.click_type);
150 script_step.
text = step.text;
154 script_step.
region = step.region;
155 script_step.
format = step.format;
157#if defined(YAZE_WITH_GRPC)
158 script_step.
expect_status = ::yaze::test::HarnessStatusToString(step.final_status);
162 if (!step.final_error_message.empty()) {
169 script.
steps.push_back(std::move(script_step));
179 recording_id_.clear();
181 started_at_ = absl::InfinitePast();
188 if (!recording_ || suspended_) {
195 steps_.push_back(std::move(copy));
200 return absl::FailedPreconditionError(
"TestManager unavailable");
203#if !defined(YAZE_WITH_GRPC)
204 return absl::OkStatus();
206 for (
auto& step : steps_) {
207 if (step.test_id.empty()) {
211 const absl::Time deadline = absl::Now() + kTestCompletionTimeout;
212 while (absl::Now() < deadline) {
213 absl::StatusOr<test::HarnessTestExecution> execution =
215 if (!execution.ok()) {
216 absl::SleepFor(kPollInterval);
220 step.final_status = execution->status;
221 step.final_error_message = execution->error_message;
222 step.assertion_failures = execution->assertion_failures;
223 step.metrics = execution->metrics;
225 if (execution->status == test::HarnessTestStatus::kQueued ||
226 execution->status == test::HarnessTestStatus::kRunning) {
227 absl::SleepFor(kPollInterval);
234 return absl::OkStatus();
239 return absl::StrFormat(
240 "rec_%s", absl::FormatTime(
"%Y%m%dT%H%M%S", absl::Now(),
241 absl::UTCTimeZone()));
ScopedSuspension(TestRecorder *recorder, bool active)
void RecordStepLocked(const RecordedStep &step) ABSL_EXCLUSIVE_LOCKS_REQUIRED(mu_)
static std::string GenerateRecordingId()
absl::StatusOr< StopRecordingSummary > StopLocked(const std::string &recording_id, bool discard) ABSL_EXCLUSIVE_LOCKS_REQUIRED(mu_)
absl::Status PopulateFinalStatusLocked() ABSL_EXCLUSIVE_LOCKS_REQUIRED(mu_)
TestManager *const test_manager_
TestRecorder(TestManager *test_manager)
absl::StatusOr< std::string > Start(const RecordingOptions &options)
absl::StatusOr< StopRecordingSummary > Stop(const std::string &recording_id, bool discard)
ScopedSuspension Suspend()
static const char * ActionTypeToString(ActionType type)
absl::StatusOr< std::string > StartLocked(const RecordingOptions &options) ABSL_EXCLUSIVE_LOCKS_REQUIRED(mu_)
void RecordStep(const RecordedStep &step)
std::string CurrentRecordingId() const
static absl::Status WriteToFile(const TestScript &script, const std::string &path)
#define RETURN_IF_ERROR(expression)
constexpr absl::Duration kPollInterval
constexpr absl::Duration kTestCompletionTimeout
Main namespace for the application.
std::vector< std::string > expect_assertion_failures
std::string expect_status
std::string expect_message
std::map< std::string, int32_t > expect_metrics
std::vector< TestScriptStep > steps