/* vim:set ts=2 sw=2 sts=2 et: */ /** * \author Marcus Holland-Moritz (github@mhxnet.de) * \copyright Copyright (c) Marcus Holland-Moritz * * This file is part of dwarfs. * * dwarfs is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * dwarfs is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with dwarfs. If not, see . */ #include #include #include #include #include #include #include #include #include #include #include #include "dwarfs/categorizer.h" #include "dwarfs/mmap.h" #include "test_logger.h" using namespace dwarfs; namespace fs = std::filesystem; namespace po = boost::program_options; namespace {} // namespace template class fits_categorizer_fixture : public Base { protected: void SetUp() override { lgr.clear(); } void create_catmgr() { create_catmgr({}); } void create_catmgr(std::vector args) { auto& catreg = categorizer_registry::instance(); po::options_description opts; catreg.add_options(opts); args.insert(args.begin(), "program"); po::variables_map vm; auto parsed = po::parse_command_line(args.size(), args.data(), opts); po::store(parsed, vm); po::notify(vm); catmgr = std::make_shared(lgr); catmgr->add(catreg.create(lgr, "fits", vm)); } public: auto categorize(fs::path const& path, std::span data) { auto job = catmgr->job(path); job.set_total_size(data.size()); job.categorize_random_access(data); job.categorize_sequential(data); return job.result(); } std::shared_ptr catmgr; test::test_logger lgr{logger::INFO}; }; using fits_categorizer = fits_categorizer_fixture<::testing::Test>; TEST_F(fits_categorizer, requirements) { create_catmgr(); EXPECT_THAT( [&] { auto cat = catmgr->category_value("fits/image").value(); catmgr->set_metadata_requirements(cat, R"({"foo": ["set", ["bar"]]})"); }, ::testing::ThrowsMessage( "unsupported metadata requirements: foo")); EXPECT_NO_THROW(catmgr->set_metadata_requirements( catmgr->category_value("fits/image").value(), R"({})")); } namespace { constexpr std::string_view fits_header{ // clang-format off // 0 1 2 3 4 5 6 7 8 // 12345678901234567890123456789012345678901234567890123456789012345678901234567890 "SIMPLE = T / file does conform to FITS standard " "BITPIX = 16 / number of bits per data pixel " "NAXIS = 2 / number of data axes " "NAXIS1 = 16 / length of data axis 1 " "NAXIS2 = 8 / length of data axis 2 " "EXTEND = T / FITS dataset may contain extensions " "END " // clang-format on }; void fill_fits_header(std::span data) { std::memcpy(data.data(), fits_header.data(), fits_header.size()); std::memset(data.data() + fits_header.size(), ' ', 2880 - fits_header.size()); } } // namespace TEST_F(fits_categorizer, unused_lsb_count_test) { create_catmgr(); alignas(2) std::array data; std::fill(data.begin(), data.end(), 0); auto metadata_category = catmgr->category_value("fits/metadata").value(); auto image_category = catmgr->category_value("fits/image").value(); std::map> categories; for (size_t offset = 0; offset < 64; offset += 2) { std::span fits{data.data() + offset, 2 * 2880}; fill_fits_header(fits); std::span image{reinterpret_cast(fits.data() + 2880), 8 * 16}; for (auto& pixel : image) { for (unsigned unused_lsb_count = 0; unused_lsb_count <= 8; ++unused_lsb_count) { pixel = folly::Endian::big(1 << unused_lsb_count); auto job = catmgr->job( fmt::format("test-{}-{}-{}", offset, pixel, unused_lsb_count)); job.set_total_size(fits.size()); job.categorize_random_access(fits); auto frag = job.result(); auto fs = frag.span(); ASSERT_EQ(3, fs.size()); EXPECT_EQ(metadata_category, fs[0].category().value()); EXPECT_EQ(2880, fs[0].size()); EXPECT_EQ(image_category, fs[1].category().value()); EXPECT_EQ(256, fs[1].size()); EXPECT_EQ(metadata_category, fs[2].category().value()); EXPECT_EQ(2624, fs[2].size()); categories[fs[1].category()].insert(unused_lsb_count); pixel = 0; } } } EXPECT_EQ(9, categories.size()); for (auto& [cat, unused_lsb_counts] : categories) { EXPECT_EQ(1, unused_lsb_counts.size()); unsigned unused_lsb_count = *unused_lsb_counts.begin(); auto json = catmgr->category_metadata(cat); auto metadata = folly::parseJson(json); EXPECT_EQ(unused_lsb_count, metadata["unused_lsb_count"].asInt()); } }