tesseract v5.3.3.20231005
tfile_test.cc
Go to the documentation of this file.
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 "serialis.h"
13
14#include "include_gunit.h"
15
16namespace tesseract {
17
18// Tests TFile and std::vector serialization by serializing and
19// writing/reading.
20
21class TfileTest : public ::testing::Test {
22protected:
23 void SetUp() override {
24 std::locale::global(std::locale(""));
25 }
26
27 TfileTest() = default;
28
29 // Some data to serialize.
30 class MathData {
31 public:
32 MathData() : num_squares_(0), num_triangles_(0) {}
33 void Setup() {
34 // Setup some data.
35 for (int s = 0; s < 42; ++s) {
36 squares_.push_back(s * s);
37 }
38 num_squares_ = squares_.size();
39 for (int t = 0; t < 52; ++t) {
40 triangles_.push_back(t * (t + 1) / 2);
41 }
42 num_triangles_ = triangles_.size();
43 }
44 void ExpectEq(const MathData &other) {
45 // Check the data.
46 EXPECT_EQ(num_squares_, other.num_squares_);
47 for (unsigned s = 0; s < squares_.size(); ++s) {
48 EXPECT_EQ(squares_[s], other.squares_[s]);
49 }
50 EXPECT_EQ(num_triangles_, other.num_triangles_);
51 for (unsigned s = 0; s < triangles_.size(); ++s) {
52 EXPECT_EQ(triangles_[s], other.triangles_[s]);
53 }
54 }
55 bool Serialize(TFile *fp) {
56 if (fp->FWrite(&num_squares_, sizeof(num_squares_), 1) != 1) {
57 return false;
58 }
59 if (!fp->Serialize(squares_)) {
60 return false;
61 }
62 if (fp->FWrite(&num_triangles_, sizeof(num_triangles_), 1) != 1) {
63 return false;
64 }
65 if (!fp->Serialize(triangles_)) {
66 return false;
67 }
68 return true;
69 }
70 bool DeSerialize(TFile *fp) {
71 if (fp->FReadEndian(&num_squares_, sizeof(num_squares_), 1) != 1) {
72 return false;
73 }
74 if (!fp->DeSerialize(squares_)) {
75 return false;
76 }
77 if (fp->FReadEndian(&num_triangles_, sizeof(num_triangles_), 1) != 1) {
78 return false;
79 }
80 if (!fp->DeSerialize(triangles_)) {
81 return false;
82 }
83 return true;
84 }
86 ReverseN(&num_squares_, sizeof(num_squares_));
87 if (fp->FWrite(&num_squares_, sizeof(num_squares_), 1) != 1) {
88 return false;
89 }
90 // Write an additional reversed size before the vector, which will get
91 // used as its size on reading.
92 if (fp->FWrite(&num_squares_, sizeof(num_squares_), 1) != 1) {
93 return false;
94 }
95 for (int &square : squares_) {
96 ReverseN(&square, sizeof(square));
97 }
98 if (!fp->Serialize(squares_)) {
99 return false;
100 }
101 ReverseN(&num_triangles_, sizeof(num_triangles_));
102 if (fp->FWrite(&num_triangles_, sizeof(num_triangles_), 1) != 1) {
103 return false;
104 }
105 if (fp->FWrite(&num_triangles_, sizeof(num_triangles_), 1) != 1) {
106 return false;
107 }
108 for (auto &triangle : triangles_) {
109 ReverseN(&triangle, sizeof(triangles_[0]));
110 }
111 return fp->Serialize(triangles_);
112 }
114 if (fp->FReadEndian(&num_squares_, sizeof(num_squares_), 1) != 1) {
115 return false;
116 }
117 if (!fp->DeSerialize(squares_)) {
118 return false;
119 }
120 // The first element is the size that was written, so we will delete it
121 // and read the last element separately.
122 int last_element;
123 if (fp->FReadEndian(&last_element, sizeof(last_element), 1) != 1) {
124 return false;
125 }
126 squares_.erase(squares_.begin());
127 squares_.push_back(last_element);
128 if (fp->FReadEndian(&num_triangles_, sizeof(num_triangles_), 1) != 1) {
129 return false;
130 }
131 if (!fp->DeSerialize(triangles_)) {
132 return false;
133 }
134 if (fp->FReadEndian(&last_element, sizeof(last_element), 1) != 1) {
135 return false;
136 }
137 triangles_.erase(triangles_.begin());
138 triangles_.push_back(last_element);
139 return true;
140 }
141
142 private:
143 std::vector<int> squares_;
144 int num_squares_;
145 std::vector<int> triangles_;
146 int num_triangles_;
147 };
148};
149
151 // This test verifies that Tfile can serialize a class.
152 MathData m1;
153 m1.Setup();
154 std::vector<char> data;
155 TFile fpw;
156 fpw.OpenWrite(&data);
157 EXPECT_TRUE(m1.Serialize(&fpw));
158 TFile fpr;
159 EXPECT_TRUE(fpr.Open(&data[0], data.size()));
160 MathData m2;
161 EXPECT_TRUE(m2.DeSerialize(&fpr));
162 m1.ExpectEq(m2);
163 MathData m3;
164 EXPECT_FALSE(m3.DeSerialize(&fpr));
165 fpr.Rewind();
166 EXPECT_TRUE(m3.DeSerialize(&fpr));
167 m1.ExpectEq(m3);
168}
169
171 // This test verifies that Tfile can interleave FGets with binary data.
172 MathData m1;
173 std::string line_str = "This is a textline with a newline\n";
174 m1.Setup();
175 std::vector<char> data;
176 TFile fpw;
177 fpw.OpenWrite(&data);
178 EXPECT_TRUE(m1.Serialize(&fpw));
179 EXPECT_EQ(1, fpw.FWrite(line_str.data(), line_str.size(), 1));
180 EXPECT_TRUE(m1.Serialize(&fpw));
181 // Now get back the 2 copies of m1 with the line in between.
182 TFile fpr;
183 EXPECT_TRUE(fpr.Open(&data[0], data.size()));
184 MathData m2;
185 EXPECT_TRUE(m2.DeSerialize(&fpr));
186 m1.ExpectEq(m2);
187 const int kBufsize = 1024;
188 char buffer[kBufsize + 1];
189 EXPECT_EQ(buffer, fpr.FGets(buffer, kBufsize));
190 EXPECT_STREQ(line_str.c_str(), buffer);
191 MathData m3;
192 EXPECT_TRUE(m3.DeSerialize(&fpr));
193 m1.ExpectEq(m3);
194}
195
196TEST_F(TfileTest, BigEndian) {
197 // This test verifies that Tfile can auto-reverse big-endian data.
198 MathData m1;
199 m1.Setup();
200 std::vector<char> data;
201 TFile fpw;
202 fpw.OpenWrite(&data);
203 EXPECT_TRUE(m1.SerializeBigEndian(&fpw));
204 TFile fpr;
205 EXPECT_TRUE(fpr.Open(&data[0], data.size()));
206 fpr.set_swap(true);
207 MathData m2;
208 EXPECT_TRUE(m2.DeSerializeBigEndian(&fpr));
209 // That serialize was destructive, so test against a fresh MathData.
210 MathData m3;
211 m3.Setup();
212 m3.ExpectEq(m2);
213}
214
215} // namespace tesseract
#define EXPECT_EQ(val1, val2)
Definition: gtest.h:2043
#define EXPECT_TRUE(condition)
Definition: gtest.h:1982
#define EXPECT_STREQ(s1, s2)
Definition: gtest.h:2112
#define EXPECT_FALSE(condition)
Definition: gtest.h:1986
void ReverseN(void *ptr, int num_bytes)
Definition: helpers.h:184
bool Serialize(FILE *fp, const std::vector< T > &data)
Definition: helpers.h:236
TEST_F(EuroText, FastLatinOCR)
void OpenWrite(std::vector< char > *data)
Definition: serialis.cpp:246
size_t FWrite(const void *buffer, size_t size, size_t count)
Definition: serialis.cpp:272
size_t FReadEndian(void *buffer, size_t size, size_t count)
Definition: serialis.cpp:210
bool DeSerialize(std::string &data)
Definition: serialis.cpp:94
bool Serialize(const std::string &data)
Definition: serialis.cpp:107
void set_swap(bool value)
Definition: serialis.h:75
char * FGets(char *buffer, int buffer_size)
Definition: serialis.cpp:195
bool Open(const char *filename, FileReader reader)
Definition: serialis.cpp:140
void SetUp() override
Definition: tfile_test.cc:23
bool DeSerializeBigEndian(TFile *fp)
Definition: tfile_test.cc:113
bool SerializeBigEndian(TFile *fp)
Definition: tfile_test.cc:85
void ExpectEq(const MathData &other)
Definition: tfile_test.cc:44