/
spivag
/
command_occ
Обзор
Документация
Войти
/
spivag
/
command_occ
Код
Запросы
1
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
initial
tests/test_document_constraints_serialization.cpp
197 строк
8 KB
Spivakov
Initial
10 апр 2026, 13:45
10 апр 2026, 13:45
b2ad868
Код
Авторство
О чём код?
/// @file test_document_constraints_serialization.cpp /// @brief Тест сериализации/десериализации документа с геометрическими ограничениями /// @project gtests /// /// (c) Alexander Spivakov on 15.12.2025. /// #include <gtest/gtest.h> #include <part_structure.h> #include <part_mating.h> #include <nlohmann-json/document_serialize.h> #include <nlohmann-json/document_deserialize.h> #include <demo_conjugate_3_parts.hxx> #include <sstream> /// @brief Подсчет количества ограничений в экземпляре детали /// @param instance Экземпляр детали /// @return Количество ограничений static size_t CountConstraints( std::shared_ptr< PartInstance > const& instance ) { if ( !instance ) return 0; size_t count = 0; auto constraintsIterator = instance->GetConstraintsIterator(); while ( constraintsIterator->HasNext() ) { count++; constraintsIterator->Next(); } return count; } /// @brief Подсчет общего количества ограничений во всех экземплярах документа /// @param document Документ /// @return Общее количество ограничений static size_t CountAllConstraints( Document const& document ) { size_t totalCount = 0; // Получить корневую деталь auto rootWeak = document.GetRootPart(); if ( auto root = rootWeak.lock() ) { // Подсчитать ограничения в корневой детали totalCount += CountConstraints( root ); // Рекурсивно подсчитать ограничения во всех вложенных деталях std::vector< std::shared_ptr< PartInstance > > toProcess{ root }; std::set< PartInstance* > visited; while ( !toProcess.empty() ) { auto current = toProcess.back(); toProcess.pop_back(); if ( !current || visited.count( current.get() ) > 0 ) continue; visited.insert( current.get() ); totalCount += CountConstraints( current ); // Добавить все вложенные экземпляры auto instancesIterator = current->GetInstancesIterator(); while ( instancesIterator->HasNext() ) { auto refWeak = instancesIterator->PartReference(); if ( auto ref = refWeak.lock() ) { if ( auto referenced = ref->ReferencedInstance().lock() ) { if ( visited.count( referenced.get() ) == 0 ) toProcess.push_back( referenced ); } } instancesIterator->Next(); } } } return totalCount; } TEST( DocumentConstraintsSerialization, Conjugate3Parts ) { // Создать документ с ограничениями auto document = demo::Conjugate3Parts::ExcentricAssembly(); ASSERT_NE( nullptr, document ); // Подсчитать количество ограничений в исходном документе size_t originalConstraintsCount = CountAllConstraints( *document ); // Ожидаем, что в примере есть ограничения EXPECT_GT( originalConstraintsCount, 0 ) << "Исходный документ должен содержать ограничения"; // Сериализовать документ std::stringstream buffer; Store( *document, buffer ); // Проверить, что буфер не пустой std::string serialized = buffer.str(); EXPECT_GT( serialized.length(), 0 ) << "Сериализованный документ не должен быть пустым"; // Десериализовать документ Document restoredDocument; ASSERT_NO_THROW( restoredDocument = Restore( buffer ) ); // Подсчитать количество ограничений в восстановленном документе size_t restoredConstraintsCount = CountAllConstraints( restoredDocument ); // Проверить, что количество ограничений совпадает EXPECT_EQ( originalConstraintsCount, restoredConstraintsCount ) << "Количество ограничений должно совпадать: исходный=" << originalConstraintsCount << ", восстановленный=" << restoredConstraintsCount; } // TODO: Эти тесты требуют доработки сериализации деталей без геометрии // Сейчас система сериализации ожидает, что детали содержат геометрию (формообразующие элементы) // Для сериализации сборок без геометрии нужно доработать логику в document_serialize.cpp /* TEST( DocumentConstraintsSerialization, EmptyDocument ) { // Создать документ с пустой деталью Document document; auto emptyPart = document.AddPart( "EmptyPart" ).lock(); ASSERT_NE( nullptr, emptyPart ); document.SetRootPart( emptyPart ); // Подсчитать количество ограничений size_t originalConstraintsCount = CountAllConstraints( document ); EXPECT_EQ( 0, originalConstraintsCount ); // Сериализовать и десериализовать std::stringstream buffer; Store( document, buffer ); Document restoredDocument; ASSERT_NO_THROW( restoredDocument = Restore( buffer ) ); size_t restoredConstraintsCount = CountAllConstraints( restoredDocument ); EXPECT_EQ( 0, restoredConstraintsCount ); } TEST( DocumentConstraintsSerialization, SimpleAssemblyWithConstraints ) { // Создать простую сборку с ограничениями Document document; auto part1 = document.AddPart( "Part1" ).lock(); ASSERT_NE( nullptr, part1 ); auto part2 = document.AddPart( "Part2" ).lock(); ASSERT_NE( nullptr, part2 ); auto rootPart = document.AddPart( "Root" ).lock(); ASSERT_NE( nullptr, rootPart ); // Добавить вставки auto ref1 = rootPart->AddPartInstance( part1, MbPlacement3D{}, "Ref1" ); auto ref2 = rootPart->AddPartInstance( part2, MbPlacement3D{}, "Ref2" ); // Создать ограничения (без топологии, так как у нас нет геометрии) std::shared_ptr< TopologyHandle > topo{}; ConstraintElement ce1( ref1, topo ); ConstraintElement ce2( ref2, topo ); // Добавить ограничение через RegisterConstraint auto coaxialConstraint = CoaxialConstraint( ce1, ce2, GCM_constraint{} ); rootPart->RegisterConstraint( PartInstance::ConstraintVariant{ coaxialConstraint } ); auto coincidenceConstraint = CoincidenceConstraint( ce1, ce2, MateOrientation::same, GCM_constraint{} ); rootPart->RegisterConstraint( PartInstance::ConstraintVariant{ coincidenceConstraint } ); document.SetRootPart( rootPart ); // Подсчитать ограничения size_t originalConstraintsCount = CountAllConstraints( document ); // Ожидаем 2 ограничения, зарегистрированных напрямую EXPECT_EQ( 2, originalConstraintsCount ) << "Должно быть 2 зарегистрированных ограничения"; // Сериализовать и десериализовать std::stringstream buffer; Store( document, buffer ); Document restoredDocument; ASSERT_NO_THROW( restoredDocument = Restore( buffer ) ); size_t restoredConstraintsCount = CountAllConstraints( restoredDocument ); EXPECT_EQ( originalConstraintsCount, restoredConstraintsCount ) << "Количество ограничений должно совпадать: исходный=" << originalConstraintsCount << ", восстановленный=" << restoredConstraintsCount; } */