chore: initial project scaffold from architecture design
- 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>
This commit is contained in:
102
tests/test_rawloader.cpp
Normal file
102
tests/test_rawloader.cpp
Normal file
@@ -0,0 +1,102 @@
|
||||
#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
|
||||
}
|
||||
Reference in New Issue
Block a user