geopro/tests/app/test_scatter_data_ops.cpp

134 lines
5.5 KiB
C++
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include <gtest/gtest.h>
#include <cmath>
#include <QJsonObject>
#include "panels/chart/ScatterDataOps.hpp"
using namespace geopro::app;
using geopro::core::ScatterField;
TEST(ScatterDataOps, ValueTypeFromCode) {
EXPECT_EQ(scatterValueTypeFromCode(QStringLiteral("linearity")), ScatterValueType::Linearity);
EXPECT_EQ(scatterValueTypeFromCode(QStringLiteral("inverse")), ScatterValueType::Inverse);
EXPECT_EQ(scatterValueTypeFromCode(QStringLiteral("logarithm")), ScatterValueType::Logarithm);
// 未知回退线性。
EXPECT_EQ(scatterValueTypeFromCode(QStringLiteral("xyz")), ScatterValueType::Linearity);
}
TEST(ScatterDataOps, ApplyValueTypeLinearIsIdentity) {
std::vector<double> v{1.0, 10.0, 100.0};
auto out = applyScatterValueType(v, ScatterValueType::Linearity);
ASSERT_EQ(out.size(), 3u);
EXPECT_DOUBLE_EQ(out[0], 1.0);
EXPECT_DOUBLE_EQ(out[2], 100.0);
}
TEST(ScatterDataOps, ApplyValueTypeInverse) {
std::vector<double> v{2.0, 0.0, -4.0};
auto out = applyScatterValueType(v, ScatterValueType::Inverse);
EXPECT_DOUBLE_EQ(out[0], 0.5);
EXPECT_DOUBLE_EQ(out[1], 0.0); // v==0 → 保持 0避免 inf
EXPECT_DOUBLE_EQ(out[2], -0.25);
}
TEST(ScatterDataOps, ApplyValueTypeLog) {
std::vector<double> v{100.0, 0.0, -5.0};
auto out = applyScatterValueType(v, ScatterValueType::Logarithm);
EXPECT_DOUBLE_EQ(out[0], 2.0); // log10(100)
EXPECT_DOUBLE_EQ(out[1], 0.0); // v<=0 → 保持原值
EXPECT_DOUBLE_EQ(out[2], -5.0); // v<=0 → 保持原值
}
TEST(ScatterDataOps, CollectIdsForHideTakesVisible) {
ScatterField f;
f.id = {"a", "b", "c", ""};
f.displayStatus = {0, 1, 0, 0}; // a,c 可见b 隐藏;空 id 跳过
// 隐藏取可见点a, c
auto hideIds = collectScatterIds(f, /*hide*/ true);
ASSERT_EQ(hideIds.size(), 2);
EXPECT_EQ(hideIds.at(0).toString().toStdString(), "a");
EXPECT_EQ(hideIds.at(1).toString().toStdString(), "c");
}
TEST(ScatterDataOps, CollectIdsForShowTakesHidden) {
ScatterField f;
f.id = {"a", "b", "c"};
f.displayStatus = {0, 1, 1}; // b,c 隐藏
auto showIds = collectScatterIds(f, /*hide*/ false);
ASSERT_EQ(showIds.size(), 2);
EXPECT_EQ(showIds.at(0).toString().toStdString(), "b");
EXPECT_EQ(showIds.at(1).toString().toStdString(), "c");
}
TEST(ScatterDataOps, FilterBodyFields) {
auto body = buildScatterFilterBody(QStringLiteral("ds1"), QStringLiteral("R0"), -10.5, 200.0);
EXPECT_EQ(body.value("sourceDsObjectId").toString().toStdString(), "ds1");
EXPECT_EQ(body.value("sourceVFieldCode").toString().toStdString(), "R0");
EXPECT_DOUBLE_EQ(body.value("min").toDouble(), -10.5);
EXPECT_DOUBLE_EQ(body.value("max").toDouble(), 200.0);
}
TEST(ScatterDataOps, SaveRawDataBodyNewHasName) {
auto body = buildSaveRawDataBody(QStringLiteral("ds1"), /*operationType*/ 1,
QStringLiteral("新数据"));
EXPECT_EQ(body.value("dsId").toString().toStdString(), "ds1");
EXPECT_EQ(body.value("operationType").toInt(), 1);
EXPECT_TRUE(body.contains("name"));
EXPECT_EQ(body.value("name").toString().toStdString(), std::string("新数据"));
}
TEST(ScatterDataOps, SaveRawDataBodyOverwriteOmitsName) {
auto body = buildSaveRawDataBody(QStringLiteral("ds1"), /*operationType*/ 0,
QStringLiteral("ignored"));
EXPECT_EQ(body.value("operationType").toInt(), 0);
EXPECT_FALSE(body.contains("name")); // 覆盖不带 name
}
TEST(ScatterDataOps, ToggledDisplayStatus) {
// 0=显示 → 1=隐藏1=隐藏 → 0=显示(对照原版 record.displayStatus ? 0 : 1
EXPECT_EQ(toggledDisplayStatus(0), 1);
EXPECT_EQ(toggledDisplayStatus(1), 0);
EXPECT_EQ(toggledDisplayStatus(2), 0); // 非 0 视为隐藏 → 显示
}
TEST(ScatterDataOps, HistogramBinsCountInRange) {
// 0..10 均匀 11 个点min=0 max=10 分 5 箱(宽 2
// [0,2):0,1 → 2[2,4):2,3 → 2[4,6):4,5 → 2[6,8):6,7 → 2[8,10]:8,9,10 → 3末箱右闭
std::vector<double> v{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
auto h = buildScatterHistogram(v, 0.0, 10.0, 5);
ASSERT_EQ(h.counts.size(), 5u);
EXPECT_DOUBLE_EQ(h.step, 2.0);
EXPECT_EQ(h.counts[0], 2);
EXPECT_EQ(h.counts[1], 2);
EXPECT_EQ(h.counts[2], 2);
EXPECT_EQ(h.counts[3], 2);
EXPECT_EQ(h.counts[4], 3); // 末箱含恰等于 max 的点
}
TEST(ScatterDataOps, HistogramSkipsOutOfRangeAndNonFinite) {
std::vector<double> v{-5, 0, 5, 10, 15, std::nan("")};
auto h = buildScatterHistogram(v, 0.0, 10.0, 2);
ASSERT_EQ(h.counts.size(), 2u);
// 区间外(-5,15)与 NaN 跳过;保留 0,5,10。
// [0,5):0 → 1[5,10]:5,10 → 2。
EXPECT_EQ(h.counts[0], 1);
EXPECT_EQ(h.counts[1], 2);
}
TEST(ScatterDataOps, HistogramDegenerateReturnsEmpty) {
std::vector<double> v{1, 2, 3};
EXPECT_TRUE(buildScatterHistogram(v, 5.0, 5.0, 10).counts.empty()); // min==max
EXPECT_TRUE(buildScatterHistogram(v, 0.0, 10.0, 0).counts.empty()); // binCount<=0
}
TEST(ScatterDataOps, CountInRangeClosedInterval) {
std::vector<double> v{0, 5, 10, 15, -3, std::nan("")};
// 闭区间 [0,10]0,5,10 计入15、-3 区间外NaN 跳过。
EXPECT_EQ(countScatterInRange(v, 0.0, 10.0), 3);
EXPECT_EQ(countScatterInRange(v, 5.0, 5.0), 1); // 单点闭区间
EXPECT_EQ(countScatterInRange(v, 10.0, 0.0), 0); // max<min → 0
EXPECT_EQ(countScatterInRange(v, 100.0, 200.0), 0); // 全在区间外
}