- Add CLAUDE.md with project overview, tech stack, build commands, architecture description, coding standards, and sample images section - Add full directory structure: src/, docs/, tests/, import/ - Add CMakeLists.txt with C++20, OpenCV/LibRaw/Qt6 dependencies, converter_core static lib, optional GUI, and GTest tests - Add architecture documentation: ARCHITECTURE.md, PIPELINE.md, MODULES.md - Add source skeletons for all pipeline stages: RawLoader, Preprocessor, NegativeDetector, Inverter, ColorCorrector, CropProcessor, OutputWriter, Pipeline, MainWindow, CliRunner, main.cpp - Add initial test stubs for pipeline and rawloader - Add sample ARW files in import/ for integration testing Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
103 lines
3.4 KiB
C++
103 lines
3.4 KiB
C++
#include <gtest/gtest.h>
|
|
|
|
#include "converter/rawloader/RawLoader.h"
|
|
|
|
#include <filesystem>
|
|
|
|
using namespace photoconv;
|
|
|
|
#ifndef TEST_DATA_DIR
|
|
#define TEST_DATA_DIR "import"
|
|
#endif
|
|
|
|
static const std::filesystem::path kTestDataDir{TEST_DATA_DIR};
|
|
|
|
// ──────────────────────────────────────────────
|
|
// File validation tests
|
|
// ──────────────────────────────────────────────
|
|
|
|
TEST(RawLoaderTest, RejectsNonexistentFile) {
|
|
RawLoader loader;
|
|
auto result = loader.load("/nonexistent/file.arw");
|
|
|
|
ASSERT_FALSE(result.has_value());
|
|
EXPECT_EQ(result.error().code, ErrorCode::FileNotFound);
|
|
}
|
|
|
|
TEST(RawLoaderTest, RejectsUnsupportedFormat) {
|
|
// Create a temporary file with unsupported extension
|
|
auto temp = std::filesystem::temp_directory_path() / "test.xyz";
|
|
{
|
|
std::ofstream f(temp);
|
|
f << "dummy";
|
|
}
|
|
|
|
RawLoader loader;
|
|
auto result = loader.load(temp);
|
|
|
|
ASSERT_FALSE(result.has_value());
|
|
EXPECT_EQ(result.error().code, ErrorCode::UnsupportedFormat);
|
|
|
|
std::filesystem::remove(temp);
|
|
}
|
|
|
|
// ──────────────────────────────────────────────
|
|
// RAW loading integration tests (require test data)
|
|
// ──────────────────────────────────────────────
|
|
|
|
TEST(RawLoaderTest, LoadsArwFile) {
|
|
auto arw_path = kTestDataDir / "DSC09246.ARW";
|
|
if (!std::filesystem::exists(arw_path)) {
|
|
GTEST_SKIP() << "Test data not available: " << arw_path;
|
|
}
|
|
|
|
RawLoader loader;
|
|
auto result = loader.load(arw_path);
|
|
|
|
ASSERT_TRUE(result.has_value()) << result.error().format();
|
|
|
|
// Verify 16-bit BGR output
|
|
EXPECT_EQ(result->rgb.type(), CV_16UC3);
|
|
EXPECT_GT(result->rgb.cols, 0);
|
|
EXPECT_GT(result->rgb.rows, 0);
|
|
|
|
// Verify metadata was populated
|
|
EXPECT_FALSE(result->metadata.camera_make.empty());
|
|
EXPECT_GT(result->metadata.raw_width, 0);
|
|
EXPECT_GT(result->metadata.raw_height, 0);
|
|
}
|
|
|
|
TEST(RawLoaderTest, MetadataContainsSonyMake) {
|
|
auto arw_path = kTestDataDir / "DSC09246.ARW";
|
|
if (!std::filesystem::exists(arw_path)) {
|
|
GTEST_SKIP() << "Test data not available: " << arw_path;
|
|
}
|
|
|
|
RawLoader loader;
|
|
auto result = loader.load(arw_path);
|
|
ASSERT_TRUE(result.has_value());
|
|
|
|
// Sony ARW files should have "Sony" as make
|
|
EXPECT_EQ(result->metadata.camera_make, "Sony");
|
|
}
|
|
|
|
// ──────────────────────────────────────────────
|
|
// Pixel integrity tests
|
|
// ──────────────────────────────────────────────
|
|
|
|
TEST(RawLoaderTest, OutputIsNonTrivial) {
|
|
auto arw_path = kTestDataDir / "DSC09246.ARW";
|
|
if (!std::filesystem::exists(arw_path)) {
|
|
GTEST_SKIP() << "Test data not available: " << arw_path;
|
|
}
|
|
|
|
RawLoader loader;
|
|
auto result = loader.load(arw_path);
|
|
ASSERT_TRUE(result.has_value());
|
|
|
|
// Image should have non-zero content (not all black or all white)
|
|
cv::Scalar mean_val = cv::mean(result->rgb);
|
|
EXPECT_GT(mean_val[0], 100.0); // Not all black
|
|
EXPECT_LT(mean_val[0], 65000.0); // Not all white
|
|
}
|