Files
OrcaSlicer/tests/slic3rutils/test_bambu_filament_ids.cpp
T
HanifKoh 84657ff11e Add Missing Includes Across the Remaining Sources and Tests (#16071)
* Ignore Clipper, libpng, mcut and Boost.Polygon Internals in clang-tidy

Each only works through a wrapper or umbrella header: libslic3r/clipper.hpp or clipper_z.hpp configure Clipper before including it, png.h pulls in libpng's config headers, and Boost.Polygon's headers only compile through polygon.hpp or voronoi.hpp.

* Ignore minilzo's Config Headers in clang-tidy

lzoconf.h and lzodefs.h are internal to minilzo.h, which is what the code includes.

* Add Missing Includes Across the Remaining Sources and Tests

Covers src/slic3r/Utils, src/slic3r/plugin, src/slic3r/Config, src/libvgcode, src/dev-utils, src/OrcaSlicer.cpp and tests/, the directories left after src/slic3r/GUI and src/libslic3r. Generated with clang-tidy misc-include-cleaner. libvgcode's own headers are included by relative path as in the rest of that library, and Catch2 and pybind11 with angle brackets as elsewhere in the repo.

* Make the GUI and Test Headers Compile on Their Own

Each now includes, or forward-declares, what it uses instead of relying on what its includers happened to include first. Headers that only compile on one platform, or that nothing built includes, are left alone.

* Keep Windows and nanosvg Setup Ahead of the Added Includes

OrcaSlicer.cpp and several tests set _WIN32_WINNT, WIN32_LEAN_AND_MEAN or NOMINMAX before including Windows.h, and the profile validator defines NANOSVG_IMPLEMENTATION before any libslic3r header. The added includes had landed above those blocks, which broke the Windows build.

* Add the GUI Includes the First Pass Missed

Covers headers that only became editable once they compiled on their own, and wx symbols whose suggested header changed as the clang-tidy ignore list grew after the src/slic3r/GUI pass.

* Keep the Added Test Includes Below the NOMINMAX Guard

test_marchingsquares.cpp and test_texture_displacement.cpp had includes inside #ifndef NOMINMAX, which the tests inherit as defined on Windows from libslic3r, so those were skipped there. .clang-tidy also ignores the MSVC STL and UCRT internals, Boost.Multiprecision's fwd.hpp and CPython's Windows include directory, as in #16068.
2026-10-03 13:45:21 +08:00

84 lines
3.9 KiB
C++

#include <catch2/catch_all.hpp>
#include <boost/filesystem.hpp>
#include <boost/nowide/fstream.hpp>
#include <nlohmann/json.hpp>
#include <string>
#include <catch2/catch_test_macros.hpp>
#include "libslic3r/Utils.hpp"
#include "slic3r/Utils/BBLPrinterAgent.hpp"
#include "slic3r/Utils/OrcaPrinterAgent.hpp"
using json = nlohmann::json;
using namespace Slic3r;
namespace {
// Point resources_dir() at the repo's own tree for the lifetime of a test and restore it
// afterwards, mirroring ScopedResourcesDir (which only ever makes a throwaway directory).
// PROFILES_DIR is <repo>/resources/profiles; the map lives in <repo>/resources/printers.
struct ScopedRepoResourcesDir
{
std::string previous{resources_dir()};
ScopedRepoResourcesDir() { set_resources_dir(boost::filesystem::path(PROFILES_DIR).parent_path().string()); }
~ScopedRepoResourcesDir() { set_resources_dir(previous); }
ScopedRepoResourcesDir(const ScopedRepoResourcesDir&) = delete;
ScopedRepoResourcesDir& operator=(const ScopedRepoResourcesDir&) = delete;
};
std::string orca_id_of(const std::string& bambu_id)
{
boost::nowide::ifstream file(resources_dir() + "/printers/bambu_filament_ids.json");
json doc;
file >> doc;
for (const auto& [orca_id, row] : doc["filaments"].items())
if (row["bambu_id"] == bambu_id)
return orca_id;
FAIL("no map row for " << bambu_id);
return {};
}
} // namespace
TEST_CASE("Bambu filament id map is one-to-one and leaves unmapped ids alone", "[BambuFilamentIds]")
{
const ScopedRepoResourcesDir repo_resources;
const BBLPrinterAgent bbl;
const std::string abs = orca_id_of("GFB00"); // Bambu ABS
REQUIRE(abs.rfind("OF", 0) == 0);
CHECK(bbl.from_orca_filament_id(abs) == "GFB00");
CHECK(bbl.to_orca_filament_id("GFB00") == abs);
CHECK(bbl.from_orca_filament_id("OFnotarow") == "OFnotarow");
CHECK(bbl.to_orca_filament_id("GFZZ99") == "GFZZ99"); // Bambu id we do not ship
CHECK(bbl.to_orca_filament_id("P1234567") == "P1234567"); // user root
CHECK(bbl.from_orca_filament_id("") == "");
// An agent whose printers already speak our ids inherits IPrinterAgent's identity default.
const OrcaPrinterAgent other{""};
CHECK(other.from_orca_filament_id(abs) == abs);
CHECK(other.to_orca_filament_id("GFB00") == "GFB00");
}
TEST_CASE("Payload rewrite covers nested trays, calibration lists and mapping info", "[BambuFilamentIds]")
{
const ScopedRepoResourcesDir repo_resources;
const std::string abs = orca_id_of("GFB00"), pla = orca_id_of("GFA00");
const std::string status =
R"({"print":{"ams":{"ams":[{"tray":[{"tray_info_idx":"GFB00"},{"tray_info_idx":"GFZZ99"}]}]},)"
R"("vt_tray":{"tray_info_idx":"GFA00"},"filaments":[{"filament_id":"GFA00","setting_id":"GFB00"}]}})";
json inbound = json::parse(BBLPrinterAgent::to_orca_payload(status));
CHECK(inbound["print"]["ams"]["ams"][0]["tray"][0]["tray_info_idx"] == abs);
CHECK(inbound["print"]["ams"]["ams"][0]["tray"][1]["tray_info_idx"] == "GFZZ99"); // no row: untouched
CHECK(inbound["print"]["vt_tray"]["tray_info_idx"] == pla);
CHECK(inbound["print"]["filaments"][0]["filament_id"] == pla);
CHECK(inbound["print"]["filaments"][0]["setting_id"] == "GFB00"); // not an id key: has a map row but must stay put
CHECK(json::parse(BBLPrinterAgent::from_orca_payload(inbound.dump())) == json::parse(status)); // round trip
const std::string mapping = R"([{"ams":0,"filamentId":")" + abs + R"(","filamentType":"ABS"}])";
CHECK(BBLPrinterAgent::from_orca_payload(mapping) == R"([{"ams":0,"filamentId":"GFB00","filamentType":"ABS"}])");
CHECK(BBLPrinterAgent::from_orca_payload("not json") == "not json");
CHECK(BBLPrinterAgent::from_orca_payload(R"({"print":{"command":"pushall"}})") == R"({"print":{"command":"pushall"}})");
}