1 // (C) Copyright 2017, Google Inc.
2 // Licensed under the Apache License, Version 2.0 (the "License");
3 // you may not use this file except in compliance with the License.
4 // You may obtain a copy of the License at
5 // http://www.apache.org/licenses/LICENSE-2.0
6 // Unless required by applicable law or agreed to in writing, software
7 // distributed under the License is distributed on an "AS IS" BASIS,
8 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
9 // See the License for the specific language governing permissions and
10 // limitations under the License.
11 
12 #include <string>
13 #include <utility>
14 
15 #include "include_gunit.h"
16 
17 #include "serialis.h"
18 #include "shapetable.h"
19 #include "unicharset.h"
20 
21 namespace tesseract {
22 
23 #ifndef DISABLED_LEGACY_ENGINE
24 
TmpNameToPath(const std::string & name)25 static std::string TmpNameToPath(const std::string &name) {
26   return file::JoinPath(FLAGS_test_tmpdir, name);
27 }
28 
29 // Sets up a simple shape with some unichars.
Setup352(int font_id,Shape * shape)30 static void Setup352(int font_id, Shape *shape) {
31   shape->AddToShape(3, font_id);
32   shape->AddToShape(5, font_id);
33   shape->AddToShape(2, font_id);
34 }
35 
36 // Verifies some properties of the 352 shape.
Expect352(int font_id,const Shape & shape)37 static void Expect352(int font_id, const Shape &shape) {
38   EXPECT_EQ(3, shape.size());
39   EXPECT_TRUE(shape.ContainsUnichar(2));
40   EXPECT_TRUE(shape.ContainsUnichar(3));
41   EXPECT_TRUE(shape.ContainsUnichar(5));
42   EXPECT_FALSE(shape.ContainsUnichar(1));
43   EXPECT_TRUE(shape.ContainsUnicharAndFont(2, font_id));
44   EXPECT_FALSE(shape.ContainsUnicharAndFont(2, font_id - 1));
45   EXPECT_FALSE(shape.ContainsUnicharAndFont(font_id, 2));
46   // It should be a subset of itself.
47   EXPECT_TRUE(shape.IsSubsetOf(shape));
48 }
49 
50 #endif
51 
52 // The fixture for testing Shape.
53 class ShapeTest : public testing::Test {
54 protected:
SetUp()55   void SetUp() override {
56     std::locale::global(std::locale(""));
57     file::MakeTmpdir();
58   }
59 };
60 
61 // Tests that a Shape works as expected for all the basic functions.
TEST_F(ShapeTest,BasicTest)62 TEST_F(ShapeTest, BasicTest) {
63 #ifdef DISABLED_LEGACY_ENGINE
64   // Skip test because Shape is missing.
65   GTEST_SKIP();
66 #else
67   Shape shape1;
68   EXPECT_EQ(0, shape1.size());
69   Setup352(101, &shape1);
70   Expect352(101, shape1);
71   // It should still work after file I/O.
72   std::string filename = TmpNameToPath("shapefile");
73   FILE *fp = fopen(filename.c_str(), "wb");
74   ASSERT_TRUE(fp != nullptr);
75   EXPECT_TRUE(shape1.Serialize(fp));
76   fclose(fp);
77   TFile tfp;
78   EXPECT_TRUE(tfp.Open(filename.c_str(), nullptr));
79   Shape shape2;
80   EXPECT_TRUE(shape2.DeSerialize(&tfp));
81   Expect352(101, shape2);
82   // They should be subsets of each other.
83   EXPECT_TRUE(shape1.IsSubsetOf(shape2));
84   EXPECT_TRUE(shape2.IsSubsetOf(shape1));
85   // They should be equal unichars.
86   EXPECT_TRUE(shape1.IsEqualUnichars(&shape2));
87   // and still pass afterwards.
88   Expect352(101, shape1);
89   Expect352(101, shape2);
90 #endif
91 }
92 
93 // Tests AddShape separately, as it takes quite a bit of work.
TEST_F(ShapeTest,AddShapeTest)94 TEST_F(ShapeTest, AddShapeTest) {
95 #ifdef DISABLED_LEGACY_ENGINE
96   // Skip test because Shape is missing.
97   GTEST_SKIP();
98 #else
99   Shape shape1;
100   Setup352(101, &shape1);
101   Expect352(101, shape1);
102   // Now setup a different shape with different content.
103   Shape shape2;
104   shape2.AddToShape(3, 101); // Duplicates shape1.
105   shape2.AddToShape(5, 110); // Different font to shape1.
106   shape2.AddToShape(7, 101); // Different unichar to shape1.
107   // They should NOT be subsets of each other.
108   EXPECT_FALSE(shape1.IsSubsetOf(shape2));
109   EXPECT_FALSE(shape2.IsSubsetOf(shape1));
110   // Now add shape2 to shape1.
111   shape1.AddShape(shape2);
112   // Test subsets again.
113   EXPECT_FALSE(shape1.IsSubsetOf(shape2));
114   EXPECT_TRUE(shape2.IsSubsetOf(shape1));
115   EXPECT_EQ(4, shape1.size());
116   EXPECT_FALSE(shape1.ContainsUnichar(1));
117   EXPECT_TRUE(shape1.ContainsUnicharAndFont(5, 101));
118   EXPECT_TRUE(shape1.ContainsUnicharAndFont(5, 110));
119   EXPECT_FALSE(shape1.ContainsUnicharAndFont(3, 110));
120   EXPECT_FALSE(shape1.ContainsUnicharAndFont(7, 110));
121   EXPECT_FALSE(shape1.IsEqualUnichars(&shape2));
122 #endif
123 }
124 
125 // The fixture for testing Shape.
126 class ShapeTableTest : public testing::Test {};
127 
128 // Tests that a Shape works as expected for all the basic functions.
TEST_F(ShapeTableTest,FullTest)129 TEST_F(ShapeTableTest, FullTest) {
130 #ifdef DISABLED_LEGACY_ENGINE
131   // Skip test because Shape is missing.
132   GTEST_SKIP();
133 #else
134   Shape shape1;
135   Setup352(101, &shape1);
136   // Build a shape table with the same data, but in separate shapes.
137   UNICHARSET unicharset;
138   unicharset.unichar_insert(" ");
139   for (int i = 1; i <= 10; ++i) {
140     char class_str[20];
141     snprintf(class_str, sizeof(class_str), "class%d", i);
142     unicharset.unichar_insert(class_str);
143   }
144   ShapeTable st(unicharset);
145   EXPECT_EQ(0, st.AddShape(3, 101));
146   EXPECT_EQ(1, st.AddShape(5, 101));
147   EXPECT_EQ(2, st.AddShape(2, 101));
148   EXPECT_EQ(3, st.NumShapes());
149   Expect352(101, shape1);
150   EXPECT_EQ(3, st.AddShape(shape1));
151   for (int i = 0; i < 3; ++i) {
152     EXPECT_FALSE(st.MutableShape(i)->IsEqualUnichars(&shape1));
153   }
154   EXPECT_TRUE(st.MutableShape(3)->IsEqualUnichars(&shape1));
155   EXPECT_TRUE(st.AnyMultipleUnichars());
156   st.DeleteShape(3);
157   EXPECT_FALSE(st.AnyMultipleUnichars());
158 
159   // Now merge to make a single shape like shape1.
160   EXPECT_EQ(1, st.MasterUnicharCount(0));
161   st.MergeShapes(0, 1);
162   EXPECT_EQ(3, st.MergedUnicharCount(1, 2));
163   st.MergeShapes(1, 2);
164   for (int i = 0; i < 3; ++i) {
165     EXPECT_EQ(3, st.MasterUnicharCount(i));
166     // Master font count is the sum of all the font counts in the shape, not
167     // the actual number of different fonts in the shape.
168     EXPECT_EQ(3, st.MasterFontCount(i));
169   }
170   EXPECT_EQ(0, st.MasterDestinationIndex(1));
171   EXPECT_EQ(0, st.MasterDestinationIndex(2));
172   ShapeTable st2;
173   st2.AppendMasterShapes(st, nullptr);
174   EXPECT_EQ(1, st.NumMasterShapes());
175   EXPECT_EQ(1, st2.NumShapes());
176   EXPECT_TRUE(st2.MutableShape(0)->IsEqualUnichars(&shape1));
177   EXPECT_TRUE(st2.AnyMultipleUnichars());
178 #endif
179 }
180 
181 } // namespace tesseract
182