tesseract  5.0.0
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 
16 namespace tesseract {
17 
18 // Tests TFile and std::vector serialization by serializing and
19 // writing/reading.
20 
21 class TfileTest : public ::testing::Test {
22 protected:
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 
170 TEST_F(TfileTest, FGets) {
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 
196 TEST_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
void ReverseN(void *ptr, int num_bytes)
Definition: helpers.h:189
bool Serialize(FILE *fp, const std::vector< T > &data)
Definition: helpers.h:251
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:83
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