File size: 7,138 Bytes
985c397
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
// SPDX-License-Identifier: LGPL-2.1-or-later

#include "gtest/gtest.h"
#include <gmock/gmock.h>

#include <src/App/InitApplication.h>

#include <App/Application.h>
#include <App/Document.h>
#include <App/DocumentObject.h>
#include <App/GeoFeatureGroupExtension.h>
#include <Base/Interpreter.h>

using namespace App;

// NOLINTBEGIN(readability-magic-numbers,cppcoreguidelines-avoid-magic-numbers)

class DocumentObjectTest: public ::testing::Test
{
protected:
    static void SetUpTestSuite()
    {
        tests::initApplication();
    }

    void SetUp() override
    {
        _docName = App::GetApplication().getUniqueDocumentName("test");
        _doc = App::GetApplication().newDocument(_docName.c_str(), "testUser");
    }

    void TearDown() override
    {
        App::GetApplication().closeDocument(_docName.c_str());
    }

    // NOLINTBEGIN(cppcoreguidelines-non-private-member-variables-in-classes)
    std::string _docName {};
    App::Document* _doc {};
    // NOLINTEND(cppcoreguidelines-non-private-member-variables-in-classes)
};


TEST_F(DocumentObjectTest, getSubObjectList)
{
    // Arrange

    // The name of a Part::Box added to the document
    auto boxName {_doc->addObject("Part::Box")->getNameInDocument()};
    // The name of a Part::Cylinder added to the document
    auto cylName {_doc->addObject("Part::Cylinder")->getNameInDocument()};
    // An App::Part object added to the document
    auto part {_doc->addObject("App::Part")};
    // The name of the App::Part added to the document
    auto partName {part->getNameInDocument()};
    // The name of the object used as argument for the calls of DocumentObject::getSubObjectList()
    auto subName {std::string()};

    // A vector of int used as argument for the call of DocumentObject::getSubObjectList() with
    // argument flatten not set (or set to false)
    auto sizesNoFlatten {std::vector<int>()};
    // A vector of int used as argument for the call of DocumentObject::getSubObjectList() with
    // argument flatten set to true
    auto sizesFlatten {std::vector<int>()};
    // A helper string used to compose the argument of some calls of
    // Base::Interpreter().runString()
    auto cmd {std::string()};

    // Performing a fusion to create an object that will be searched with the calls of
    // DocumentObject::getSubObjectList()
    Base::Interpreter().runString("from BOPTools import BOPFeatures");
    Base::Interpreter().runString("bp = BOPFeatures.BOPFeatures(App.activeDocument())");
    cmd = "bp.make_multi_fuse([\"";
    cmd += boxName;
    cmd += "\", \"";
    cmd += cylName;
    cmd += "\", ])";
    Base::Interpreter().runString(cmd.c_str());
    Base::Interpreter().runString("App.ActiveDocument.recompute()");
    // The name of the fusion object
    auto fuseName {_doc->getObject("Fusion")->getNameInDocument()};

    // Defining the name of the object that will be searched with the calls of
    // DocumentObject::getSubObjectList()
    subName = fuseName;
    subName += ".";
    subName += boxName;
    subName += ".Edge1";

    // Adding the fusion to the App::Part object to test the differences between calling
    // DocumentObject::getSubObjectList() with the flatten argument set to false or set to true
    cmd = "App.ActiveDocument.getObject(\"";
    cmd += partName;
    cmd += "\").addObject(App.ActiveDocument.getObject(\"";
    cmd += fuseName;
    cmd += "\"))";
    Base::Interpreter().runString(cmd.c_str());
    Base::Interpreter().runString("App.ActiveDocument.recompute()");

    // A vector of DocumentObjects used to store the result of the call to
    // DocumentObject::getSubObjectList() without the subname parameter
    auto docSubObjsNoSubName {std::vector<DocumentObject*>()};
    // A vector of DocumentObjects used to store the result of the call to
    // DocumentObject::getSubObjectList() with only the subname parameter
    auto docSubObjsWithSubName {std::vector<DocumentObject*>()};
    // A vector of DocumentObjects used to store the result of the call to
    // DocumentObject::getSubObjectList() with the parameters subname and subsizes
    auto docSubObjsWithSubSizes {std::vector<DocumentObject*>()};
    // A vector of DocumentObjects used to store the result of the call to
    // DocumentObject::getSubObjectList() with the flatten parameter set to true
    auto docSubObjsFlatten {std::vector<DocumentObject*>()};

    // Act
    docSubObjsNoSubName = part->getSubObjectList(nullptr);
    docSubObjsWithSubName = part->getSubObjectList(subName.c_str());
    docSubObjsWithSubSizes = part->getSubObjectList(subName.c_str(), &sizesNoFlatten);
    docSubObjsFlatten = part->getSubObjectList(subName.c_str(), &sizesFlatten, true);

    // Assert

    // If DocumentObject::getSubObjectList() is called without giving the subname argument it
    // returns a vector with only one entry, corresponding to the object that called the method
    EXPECT_EQ(docSubObjsNoSubName.size(), 1);
    EXPECT_EQ(docSubObjsNoSubName[0]->getID(), _doc->getObject(partName)->getID());

    // If DocumentObject::getSubObjectList() is called with the subname argument it returns a vector
    // with one entry for each sub object in the subname plus one entry with the object that called
    // the method
    EXPECT_EQ(docSubObjsWithSubName.size(), 3);
    EXPECT_EQ(docSubObjsWithSubName[0]->getID(), _doc->getObject(partName)->getID());
    EXPECT_EQ(docSubObjsWithSubName[1]->getID(), _doc->getObject(fuseName)->getID());
    EXPECT_EQ(docSubObjsWithSubName[2]->getID(), _doc->getObject(boxName)->getID());

    // If DocumentObject::getSubObjectList() is called with the subsizes argument it returns the
    // same vector of the previous case and the subsizes argument stores the positions in the
    // subname string corresponding to start of the sub objects names.
    // The position takes into account also the '.' in the subname
    EXPECT_EQ(docSubObjsWithSubSizes.size(), 3);
    EXPECT_EQ(docSubObjsWithSubSizes[0]->getID(), _doc->getObject(partName)->getID());
    EXPECT_EQ(docSubObjsWithSubSizes[1]->getID(), _doc->getObject(fuseName)->getID());
    EXPECT_EQ(docSubObjsWithSubSizes[2]->getID(), _doc->getObject(boxName)->getID());
    EXPECT_EQ(sizesNoFlatten.size(), 3);
    EXPECT_EQ(sizesNoFlatten[0], 0);
    EXPECT_EQ(sizesNoFlatten[1], strlen(fuseName) + 1);
    EXPECT_EQ(sizesNoFlatten[2], strlen(fuseName) + strlen(boxName) + 2);

    // If DocumentObject::getSubObjectList() is called with the flattened argument set to true, it
    // returns a vector with all the sub objects in the subname that don't belong to the same
    // App::GeoFeatureGroupExtension object, plus one entry with the object that called the method
    EXPECT_EQ(docSubObjsFlatten.size(), 2);
    EXPECT_EQ(docSubObjsFlatten[0]->getID(), _doc->getObject(partName)->getID());
    EXPECT_EQ(docSubObjsFlatten[1]->getID(), _doc->getObject(boxName)->getID());
    EXPECT_EQ(sizesFlatten.size(), 2);
    EXPECT_EQ(sizesFlatten[0], 0);
    EXPECT_EQ(sizesFlatten[1], strlen(fuseName) + strlen(boxName) + 2);
}

// NOLINTEND(readability-magic-numbers, cppcoreguidelines-avoid-magic-numbers)