in lib/api/unittest/CJsonOutputWriterTest.cc [42:506]
void testBucketWriteHelper(bool isInterim) {
// groups output by bucket/detector
std::ostringstream sstream;
// The output writer won't close the JSON structures until is is destroyed
{
ml::core::CJsonOutputStreamWrapper outputStream(sstream);
ml::api::CJsonOutputWriter writer("job", outputStream);
std::string partitionFieldName("tfn");
std::string partitionFieldValue("");
std::string overFieldName("pfn");
std::string overFieldValue("pfv");
std::string byFieldName("airline");
std::string byFieldValue("GAL");
std::string correlatedByFieldValue("BAW");
std::string fieldName("responsetime");
std::string function("mean");
std::string functionDescription("mean(responsetime)");
std::string emptyString;
ml::api::CHierarchicalResultsWriter::TOptionalStrOptionalStrPrDoublePrVec influences;
{
ml::api::CHierarchicalResultsWriter::SResults result11(
false, false, partitionFieldName, partitionFieldValue,
overFieldName, overFieldValue, byFieldName, byFieldValue,
correlatedByFieldValue, 1, function, functionDescription,
TDouble1Vec(1, 10090.0), TDouble1Vec(1, 6953.0), 2.24, 0.5, 0.0,
79, fieldName, influences, false, false, 1, 100);
ml::api::CHierarchicalResultsWriter::SResults result112(
false, true, partitionFieldName, partitionFieldValue,
overFieldName, overFieldValue, byFieldName, byFieldValue,
correlatedByFieldValue, 1, function, functionDescription,
TDouble1Vec(1, 10090.0), TDouble1Vec(1, 6953.0), 2.24, 0.5, 0.0,
79, fieldName, influences, false, false, 1, 100);
ml::api::CHierarchicalResultsWriter::SResults result12(
ml::api::CHierarchicalResultsWriter::E_Result, partitionFieldName,
partitionFieldValue, byFieldName, byFieldValue, correlatedByFieldValue,
1, function, functionDescription, 42.0, 79, TDouble1Vec(1, 6953.0),
TDouble1Vec(1, 10090.0), 2.24, 0.8, 0.0, -5.0, fieldName,
influences, false, true, 2, 100, EMPTY_STRING_LIST, {});
ml::api::CHierarchicalResultsWriter::SResults result13(
ml::api::CHierarchicalResultsWriter::E_SimpleCountResult,
partitionFieldName, partitionFieldValue, byFieldName, byFieldValue,
correlatedByFieldValue, 1, function, functionDescription, 42.0, 79,
TDouble1Vec(1, 6953.0), TDouble1Vec(1, 10090.0), 2.24, 0.5, 0.0, -5.0,
fieldName, influences, false, false, 3, 100, EMPTY_STRING_LIST, {});
ml::api::CHierarchicalResultsWriter::SResults result14(
ml::api::CHierarchicalResultsWriter::E_Result, partitionFieldName,
partitionFieldValue, byFieldName, byFieldValue, correlatedByFieldValue,
1, function, functionDescription, 42.0, 79, TDouble1Vec(1, 6953.0),
TDouble1Vec(1, 10090.0), 2.24, 0.0, 0.0, -5.0, fieldName,
influences, false, false, 4, 100, EMPTY_STRING_LIST, {});
// 1st bucket
BOOST_TEST_REQUIRE(writer.acceptResult(result11));
BOOST_TEST_REQUIRE(writer.acceptResult(result11));
BOOST_TEST_REQUIRE(writer.acceptResult(result112));
BOOST_TEST_REQUIRE(writer.acceptResult(result12));
BOOST_TEST_REQUIRE(writer.acceptResult(result12));
BOOST_TEST_REQUIRE(writer.acceptResult(result13));
BOOST_TEST_REQUIRE(writer.acceptResult(result13));
BOOST_TEST_REQUIRE(writer.acceptResult(result14));
BOOST_TEST_REQUIRE(writer.acceptResult(result14));
writer.acceptBucketTimeInfluencer(1, 0.01, 13.44, 70.0);
}
{
ml::api::CHierarchicalResultsWriter::SResults result21(
false, false, partitionFieldName, partitionFieldValue,
overFieldName, overFieldValue, byFieldName, byFieldValue,
correlatedByFieldValue, 2, function, functionDescription,
TDouble1Vec(1, 10090.0), TDouble1Vec(1, 6953.0), 2.24, 0.6, 0.0,
79, fieldName, influences, false, false, 1, 100);
ml::api::CHierarchicalResultsWriter::SResults result212(
false, true, partitionFieldName, partitionFieldValue,
overFieldName, overFieldValue, byFieldName, byFieldValue,
correlatedByFieldValue, 2, function, functionDescription,
TDouble1Vec(1, 10090.0), TDouble1Vec(1, 6953.0), 2.24, 0.6, 0.0,
79, fieldName, influences, false, false, 1, 100);
ml::api::CHierarchicalResultsWriter::SResults result22(
ml::api::CHierarchicalResultsWriter::E_Result, partitionFieldName,
partitionFieldValue, byFieldName, byFieldValue, correlatedByFieldValue,
2, function, functionDescription, 42.0, 79, TDouble1Vec(1, 6953.0),
TDouble1Vec(1, 10090.0), 2.24, 0.8, 0.0, -5.0, fieldName,
influences, false, true, 2, 100, EMPTY_STRING_LIST, {});
ml::api::CHierarchicalResultsWriter::SResults result23(
ml::api::CHierarchicalResultsWriter::E_SimpleCountResult,
partitionFieldName, partitionFieldValue, byFieldName, byFieldValue,
correlatedByFieldValue, 2, function, functionDescription, 42.0, 79,
TDouble1Vec(1, 6953.0), TDouble1Vec(1, 10090.0), 2.24, 0.0, 0.0, -5.0,
fieldName, influences, false, false, 3, 100, EMPTY_STRING_LIST, {});
ml::api::CHierarchicalResultsWriter::SResults result24(
ml::api::CHierarchicalResultsWriter::E_Result, partitionFieldName,
partitionFieldValue, byFieldName, byFieldValue, correlatedByFieldValue,
2, function, functionDescription, 42.0, 79, TDouble1Vec(1, 6953.0),
TDouble1Vec(1, 10090.0), 2.24, 0.0, 0.0, -5.0, fieldName,
influences, false, false, 4, 100, EMPTY_STRING_LIST, {});
// 2nd bucket
BOOST_TEST_REQUIRE(writer.acceptResult(result21));
BOOST_TEST_REQUIRE(writer.acceptResult(result21));
BOOST_TEST_REQUIRE(writer.acceptResult(result212));
BOOST_TEST_REQUIRE(writer.acceptResult(result22));
BOOST_TEST_REQUIRE(writer.acceptResult(result22));
BOOST_TEST_REQUIRE(writer.acceptResult(result23));
BOOST_TEST_REQUIRE(writer.acceptResult(result23));
BOOST_TEST_REQUIRE(writer.acceptResult(result24));
BOOST_TEST_REQUIRE(writer.acceptResult(result24));
writer.acceptBucketTimeInfluencer(2, 0.01, 13.44, 70.0);
}
{
ml::api::CHierarchicalResultsWriter::SResults result31(
false, false, partitionFieldName, partitionFieldValue,
overFieldName, overFieldValue, byFieldName, byFieldValue,
correlatedByFieldValue, 3, function, functionDescription,
TDouble1Vec(1, 10090.0), TDouble1Vec(1, 6953.0), 2.24, 0.8, 0.0,
79, fieldName, influences, false, false, 1, 100);
ml::api::CHierarchicalResultsWriter::SResults result312(
false, true, partitionFieldName, partitionFieldValue,
overFieldName, overFieldValue, byFieldName, byFieldValue,
correlatedByFieldValue, 3, function, functionDescription,
TDouble1Vec(1, 10090.0), TDouble1Vec(1, 6953.0), 2.24, 0.8, 0.0,
79, fieldName, influences, false, false, 1, 100);
ml::api::CHierarchicalResultsWriter::SResults result32(
ml::api::CHierarchicalResultsWriter::E_Result, partitionFieldName,
partitionFieldValue, byFieldName, byFieldValue, correlatedByFieldValue,
3, function, functionDescription, 42.0, 79, TDouble1Vec(1, 6953.0),
TDouble1Vec(1, 10090.0), 2.24, 0.0, 0.0, -5.0, fieldName,
influences, false, true, 2, 100, EMPTY_STRING_LIST, {});
ml::api::CHierarchicalResultsWriter::SResults result33(
ml::api::CHierarchicalResultsWriter::E_SimpleCountResult,
partitionFieldName, partitionFieldValue, byFieldName, byFieldValue,
correlatedByFieldValue, 3, function, functionDescription, 42.0, 79,
TDouble1Vec(1, 6953.0), TDouble1Vec(1, 10090.0), 2.24, 0.0, 0.0, -5.0,
fieldName, influences, false, false, 3, 100, EMPTY_STRING_LIST, {});
ml::api::CHierarchicalResultsWriter::SResults result34(
ml::api::CHierarchicalResultsWriter::E_Result, partitionFieldName,
partitionFieldValue, byFieldName, byFieldValue, correlatedByFieldValue,
3, function, functionDescription, 42.0, 79, TDouble1Vec(1, 6953.0),
TDouble1Vec(1, 10090.0), 2.24, 0.0, 0.0, -5.0, fieldName,
influences, false, false, 4, 100, EMPTY_STRING_LIST, {});
// 3rd bucket
BOOST_TEST_REQUIRE(writer.acceptResult(result31));
BOOST_TEST_REQUIRE(writer.acceptResult(result31));
BOOST_TEST_REQUIRE(writer.acceptResult(result312));
BOOST_TEST_REQUIRE(writer.acceptResult(result32));
BOOST_TEST_REQUIRE(writer.acceptResult(result32));
BOOST_TEST_REQUIRE(writer.acceptResult(result33));
BOOST_TEST_REQUIRE(writer.acceptResult(result33));
BOOST_TEST_REQUIRE(writer.acceptResult(result34));
BOOST_TEST_REQUIRE(writer.acceptResult(result34));
writer.acceptBucketTimeInfluencer(3, 0.01, 13.44, 70.0);
}
// Finished adding results
BOOST_TEST_REQUIRE(writer.endOutputBatch(isInterim, 10U));
}
json::error_code ec;
json::value arrayDoc = json::parse(sstream.str(), ec);
BOOST_TEST_REQUIRE(ec.failed() == false);
BOOST_TEST_REQUIRE(arrayDoc.is_array());
LOG_DEBUG(<< "Results:\n" << arrayDoc);
// There are 3 buckets and 3 record arrays in the order: r1, b1, r2, b2, r3, b3
BOOST_REQUIRE_EQUAL(6, arrayDoc.as_array().size());
int bucketTimes[] = {1000, 1000, 2000, 2000, 3000, 3000};
// Assert buckets
for (std::size_t i = 1; i < arrayDoc.as_array().size(); i = i + 2) {
int buckettime = bucketTimes[i];
const json::value& bucketWrapper_ = arrayDoc.as_array().at(i);
const json::object& bucketWrapper = bucketWrapper_.as_object();
BOOST_TEST_REQUIRE(bucketWrapper.contains("bucket"));
const json::value& bucket_ = bucketWrapper.at("bucket");
BOOST_TEST_REQUIRE(bucket_.is_object());
const json::object& bucket = bucket_.as_object();
BOOST_TEST_REQUIRE(bucket.contains("job_id"));
BOOST_REQUIRE_EQUAL("job", bucket.at("job_id").as_string());
// 3 detectors each have 2 records (simple count detector isn't added)
// except the population detector which has a single record and clauses
BOOST_REQUIRE_EQUAL(buckettime, bucket.at("timestamp").to_number<std::int64_t>());
BOOST_TEST_REQUIRE(bucket.contains("bucket_influencers"));
const json::value& bucketInfluencers_ = bucket.at("bucket_influencers");
BOOST_TEST_REQUIRE(bucketInfluencers_.is_array());
const json::array& bucketInfluencers = bucketInfluencers_.as_array();
BOOST_REQUIRE_EQUAL(std::size_t(1), bucketInfluencers.size());
const json::value& bucketInfluencer_ = bucketInfluencers[std::size_t(0)];
const json::object& bucketInfluencer = bucketInfluencer_.as_object();
BOOST_REQUIRE_CLOSE_ABSOLUTE(
13.44, bucketInfluencer.at("raw_anomaly_score").to_number<double>(), 0.00001);
BOOST_REQUIRE_CLOSE_ABSOLUTE(
0.01, bucketInfluencer.at("probability").to_number<double>(), 0.00001);
BOOST_REQUIRE_CLOSE_ABSOLUTE(
70.0, bucketInfluencer.at("initial_anomaly_score").to_number<double>(), 0.00001);
BOOST_TEST_REQUIRE(bucketInfluencer.contains("anomaly_score"));
BOOST_REQUIRE_CLOSE_ABSOLUTE(
70.0, bucketInfluencer.at("anomaly_score").to_number<double>(), 0.00001);
BOOST_REQUIRE_EQUAL("bucket_time",
bucketInfluencer.at("influencer_field_name").as_string());
BOOST_REQUIRE_EQUAL(79, bucket.at("event_count").to_number<std::int64_t>());
BOOST_TEST_REQUIRE(bucket.contains("anomaly_score"));
BOOST_REQUIRE_CLOSE_ABSOLUTE(
70.0, bucket.at("anomaly_score").to_number<double>(), 0.00001);
BOOST_TEST_REQUIRE(bucket.contains("initial_anomaly_score"));
BOOST_REQUIRE_CLOSE_ABSOLUTE(
70.0, bucket.at("initial_anomaly_score").to_number<double>(), 0.00001);
if (isInterim) {
BOOST_TEST_REQUIRE(bucket.contains("is_interim"));
BOOST_REQUIRE_EQUAL(isInterim, bucket.at("is_interim").as_bool());
} else {
BOOST_TEST_REQUIRE(!bucket.contains("is_interim"));
}
BOOST_REQUIRE_EQUAL(std::uint64_t(10ll),
bucket.at("processing_time_ms").to_number<std::uint64_t>());
}
for (std::size_t i = 0; i < arrayDoc.as_array().size(); i = i + 2) {
int buckettime = bucketTimes[i];
const json::value& recordsWrapper_ = arrayDoc.as_array().at(i);
const json::object& recordsWrapper = recordsWrapper_.as_object();
BOOST_TEST_REQUIRE(recordsWrapper.contains("records"));
const json::value& records_ = recordsWrapper.at("records");
BOOST_TEST_REQUIRE(records_.is_array());
const json::array& records = records_.as_array();
BOOST_REQUIRE_EQUAL(std::size_t(5), records.size());
// 1st record is for population detector
{
const json::value& record_ = records[std::size_t(0)];
const json::object& record = record_.as_object();
BOOST_TEST_REQUIRE(record.contains("job_id"));
BOOST_REQUIRE_EQUAL("job", record.at("job_id").as_string());
BOOST_TEST_REQUIRE(record.contains("detector_index"));
BOOST_REQUIRE_EQUAL(1, record.at("detector_index").to_number<std::int64_t>());
BOOST_TEST_REQUIRE(record.contains("timestamp"));
BOOST_REQUIRE_EQUAL(buckettime,
record.at("timestamp").to_number<std::int64_t>());
BOOST_TEST_REQUIRE(record.contains("probability"));
BOOST_REQUIRE_EQUAL(0.0, record.at("probability").to_number<double>());
BOOST_TEST_REQUIRE(record.contains("by_field_name"));
BOOST_REQUIRE_EQUAL("airline", record.at("by_field_name").as_string());
BOOST_TEST_REQUIRE(!record.contains("by_field_value"));
BOOST_TEST_REQUIRE(!record.contains("correlated_by_field_value"));
BOOST_TEST_REQUIRE(record.contains("function"));
BOOST_REQUIRE_EQUAL("mean", record.at("function").as_string());
BOOST_TEST_REQUIRE(record.contains("function_description"));
BOOST_REQUIRE_EQUAL("mean(responsetime)",
record.at("function_description").as_string());
BOOST_TEST_REQUIRE(record.contains("over_field_name"));
BOOST_REQUIRE_EQUAL("pfn", record.at("over_field_name").as_string());
BOOST_TEST_REQUIRE(record.contains("over_field_value"));
BOOST_REQUIRE_EQUAL("pfv", record.at("over_field_value").as_string());
BOOST_TEST_REQUIRE(record.contains("bucket_span"));
BOOST_REQUIRE_EQUAL(100, record.at("bucket_span").to_number<std::int64_t>());
// It's hard to predict what these will be, so just assert their
// presence
BOOST_TEST_REQUIRE(record.contains("initial_record_score"));
BOOST_TEST_REQUIRE(record.contains("record_score"));
if (isInterim) {
BOOST_TEST_REQUIRE(record.contains("is_interim"));
BOOST_REQUIRE_EQUAL(isInterim, record.at("is_interim").as_bool());
} else {
BOOST_TEST_REQUIRE(!record.contains("is_interim"));
}
BOOST_TEST_REQUIRE(record.contains("causes"));
const json::value& causes_ = record.at("causes");
BOOST_TEST_REQUIRE(causes_.is_array());
const json::array& causes = causes_.as_array();
BOOST_REQUIRE_EQUAL(std::size_t(2), causes.size());
for (std::size_t k = 0; k < causes.size(); k++) {
const json::value& cause_ = causes[k];
const json::object& cause = cause_.as_object();
BOOST_TEST_REQUIRE(cause.contains("probability"));
BOOST_REQUIRE_EQUAL(0.0, cause.at("probability").to_number<double>());
BOOST_TEST_REQUIRE(cause.contains("field_name"));
BOOST_REQUIRE_EQUAL("responsetime", cause.at("field_name").as_string());
BOOST_TEST_REQUIRE(cause.contains("by_field_name"));
BOOST_REQUIRE_EQUAL("airline", cause.at("by_field_name").as_string());
BOOST_TEST_REQUIRE(cause.contains("by_field_value"));
BOOST_REQUIRE_EQUAL("GAL", cause.at("by_field_value").as_string());
BOOST_TEST_REQUIRE(cause.contains("correlated_by_field_value"));
BOOST_REQUIRE_EQUAL("BAW", cause.at("correlated_by_field_value").as_string());
BOOST_TEST_REQUIRE(cause.contains("partition_field_name"));
BOOST_REQUIRE_EQUAL("tfn", cause.at("partition_field_name").as_string());
BOOST_TEST_REQUIRE(cause.contains("partition_field_value"));
BOOST_REQUIRE_EQUAL("", cause.at("partition_field_value").as_string());
BOOST_TEST_REQUIRE(cause.contains("function"));
BOOST_REQUIRE_EQUAL("mean", cause.at("function").as_string());
BOOST_TEST_REQUIRE(cause.contains("function_description"));
BOOST_REQUIRE_EQUAL("mean(responsetime)",
cause.at("function_description").as_string());
BOOST_TEST_REQUIRE(cause.contains("typical"));
BOOST_TEST_REQUIRE(cause.at("typical").is_array());
BOOST_REQUIRE_EQUAL(std::size_t(1),
cause.at("typical").as_array().size());
BOOST_REQUIRE_EQUAL(
6953.0,
cause.at("typical").as_array().at(std::size_t(0)).to_number<double>());
BOOST_TEST_REQUIRE(cause.contains("actual"));
BOOST_TEST_REQUIRE(cause.at("actual").is_array());
BOOST_REQUIRE_EQUAL(std::size_t(1),
cause.at("actual").as_array().size());
BOOST_REQUIRE_EQUAL(
10090.0,
cause.at("actual").as_array().at(std::size_t(0)).to_number<double>());
BOOST_TEST_REQUIRE(cause.contains("function"));
}
}
// Next 2 records are for metric detector
{
for (std::size_t k = 1; k < 3; k++) {
const json::value& record_ = records[k];
const json::object& record = record_.as_object();
BOOST_TEST_REQUIRE(record.contains("job_id"));
BOOST_REQUIRE_EQUAL("job", record.at("job_id").as_string());
BOOST_TEST_REQUIRE(record.contains("detector_index"));
BOOST_REQUIRE_EQUAL(
2, record.at("detector_index").to_number<std::int64_t>());
BOOST_TEST_REQUIRE(record.contains("timestamp"));
BOOST_REQUIRE_EQUAL(
buckettime, record.at("timestamp").to_number<std::int64_t>());
BOOST_TEST_REQUIRE(record.contains("probability"));
BOOST_REQUIRE_EQUAL(0.0, record.at("probability").to_number<double>());
BOOST_TEST_REQUIRE(record.contains("by_field_name"));
BOOST_REQUIRE_EQUAL("airline", record.at("by_field_name").as_string());
BOOST_TEST_REQUIRE(record.contains("by_field_value"));
BOOST_REQUIRE_EQUAL("GAL", record.at("by_field_value").as_string());
BOOST_TEST_REQUIRE(record.contains("correlated_by_field_value"));
BOOST_REQUIRE_EQUAL(
"BAW", record.at("correlated_by_field_value").as_string());
BOOST_TEST_REQUIRE(record.contains("typical"));
BOOST_TEST_REQUIRE(record.at("typical").is_array());
BOOST_REQUIRE_EQUAL(std::size_t(1),
record.at("typical").as_array().size());
BOOST_REQUIRE_EQUAL(
6953.0,
record.at("typical").as_array().at(std::size_t(0)).to_number<double>());
BOOST_TEST_REQUIRE(record.contains("actual"));
BOOST_TEST_REQUIRE(record.at("actual").is_array());
BOOST_REQUIRE_EQUAL(std::size_t(1),
record.at("actual").as_array().size());
BOOST_REQUIRE_EQUAL(
10090.0,
record.at("actual").as_array().at(std::size_t(0)).to_number<double>());
BOOST_TEST_REQUIRE(record.contains("field_name"));
BOOST_REQUIRE_EQUAL("responsetime", record.at("field_name").as_string());
BOOST_TEST_REQUIRE(record.contains("function"));
BOOST_REQUIRE_EQUAL("mean", record.at("function").as_string());
BOOST_TEST_REQUIRE(record.contains("function_description"));
BOOST_REQUIRE_EQUAL("mean(responsetime)",
record.at("function_description").as_string());
BOOST_TEST_REQUIRE(record.contains("partition_field_name"));
BOOST_REQUIRE_EQUAL("tfn", record.at("partition_field_name").as_string());
BOOST_TEST_REQUIRE(record.contains("partition_field_value"));
BOOST_REQUIRE_EQUAL("", record.at("partition_field_value").as_string());
BOOST_TEST_REQUIRE(record.contains("bucket_span"));
BOOST_REQUIRE_EQUAL(100, record.at("bucket_span").to_number<std::int64_t>());
// It's hard to predict what these will be, so just assert their
// presence
BOOST_TEST_REQUIRE(record.contains("initial_record_score"));
BOOST_TEST_REQUIRE(record.contains("record_score"));
if (isInterim) {
BOOST_TEST_REQUIRE(record.contains("is_interim"));
BOOST_REQUIRE_EQUAL(isInterim, record.at("is_interim").as_bool());
} else {
BOOST_TEST_REQUIRE(!record.contains("is_interim"));
}
}
}
// Last 2 records are for event rate detector
{
for (std::size_t k = 3; k < 5; k++) {
const json::value& record_ = records[k];
const json::object& record = record_.as_object();
BOOST_TEST_REQUIRE(record.contains("job_id"));
BOOST_REQUIRE_EQUAL("job", record.at("job_id").as_string());
BOOST_TEST_REQUIRE(record.contains("detector_index"));
BOOST_REQUIRE_EQUAL(
4, record.at("detector_index").to_number<std::int64_t>());
BOOST_TEST_REQUIRE(record.contains("timestamp"));
BOOST_REQUIRE_EQUAL(
buckettime, record.at("timestamp").to_number<std::int64_t>());
BOOST_TEST_REQUIRE(record.contains("probability"));
BOOST_REQUIRE_EQUAL(0.0, record.at("probability").to_number<double>());
BOOST_TEST_REQUIRE(record.contains("by_field_name"));
BOOST_REQUIRE_EQUAL("airline", record.at("by_field_name").as_string());
BOOST_TEST_REQUIRE(record.contains("by_field_value"));
BOOST_REQUIRE_EQUAL("GAL", record.at("by_field_value").as_string());
BOOST_TEST_REQUIRE(record.contains("correlated_by_field_value"));
BOOST_REQUIRE_EQUAL(
"BAW", record.at("correlated_by_field_value").as_string());
BOOST_TEST_REQUIRE(record.contains("typical"));
BOOST_TEST_REQUIRE(record.at("typical").is_array());
BOOST_REQUIRE_EQUAL(std::size_t(1),
record.at("typical").as_array().size());
BOOST_REQUIRE_EQUAL(
6953.0,
record.at("typical").as_array().at(std::size_t(0)).to_number<double>());
BOOST_TEST_REQUIRE(record.contains("actual"));
BOOST_TEST_REQUIRE(record.at("actual").is_array());
BOOST_REQUIRE_EQUAL(std::size_t(1),
record.at("actual").as_array().size());
BOOST_REQUIRE_EQUAL(
10090.0,
record.at("actual").as_array().at(std::size_t(0)).to_number<double>());
BOOST_TEST_REQUIRE(record.contains("function"));
// This would be count in the real case with properly generated input data
BOOST_REQUIRE_EQUAL("mean", record.at("function").as_string());
BOOST_TEST_REQUIRE(record.contains("function_description"));
BOOST_REQUIRE_EQUAL("mean(responsetime)",
record.at("function_description").as_string());
BOOST_TEST_REQUIRE(record.contains("partition_field_name"));
BOOST_REQUIRE_EQUAL("tfn", record.at("partition_field_name").as_string());
BOOST_TEST_REQUIRE(record.contains("partition_field_value"));
BOOST_REQUIRE_EQUAL("", record.at("partition_field_value").as_string());
BOOST_TEST_REQUIRE(record.contains("bucket_span"));
BOOST_REQUIRE_EQUAL(100, record.at("bucket_span").to_number<std::int64_t>());
// It's hard to predict what these will be, so just assert their
// presence
BOOST_TEST_REQUIRE(record.contains("initial_record_score"));
BOOST_TEST_REQUIRE(record.contains("record_score"));
if (isInterim) {
BOOST_TEST_REQUIRE(record.contains("is_interim"));
BOOST_REQUIRE_EQUAL(isInterim, record.at("is_interim").as_bool());
} else {
BOOST_TEST_REQUIRE(!record.contains("is_interim"));
}
}
}
}
}