tesseract/unittest/tfile_test.cc

178 lines
5.9 KiB
C++
Raw Normal View History

// (C) Copyright 2017, Google Inc.
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "genericvector.h"
#include "serialis.h"
#include "include_gunit.h"
using tesseract::TFile;
namespace {
// Tests TFile and GenericVector serialization by serializing and
// writing/reading.
class TfileTest : public ::testing::Test {
protected:
TfileTest() {}
// Some data to serialize.
class MathData {
public:
MathData() : num_squares_(0), num_triangles_(0) {}
void Setup() {
// Setup some data.
for (int s = 0; s < 42; ++s) squares_.push_back(s * s);
num_squares_ = squares_.size();
for (int t = 0; t < 52; ++t) triangles_.push_back(t * (t + 1) / 2);
num_triangles_ = triangles_.size();
}
void ExpectEq(const MathData& other) {
// Check the data.
EXPECT_EQ(num_squares_, other.num_squares_);
for (int s = 0; s < squares_.size(); ++s)
EXPECT_EQ(squares_[s], other.squares_[s]);
EXPECT_EQ(num_triangles_, other.num_triangles_);
for (int s = 0; s < triangles_.size(); ++s)
EXPECT_EQ(triangles_[s], other.triangles_[s]);
}
bool Serialize(TFile* fp) {
if (fp->FWrite(&num_squares_, sizeof(num_squares_), 1) != 1) return false;
if (!squares_.Serialize(fp)) return false;
if (fp->FWrite(&num_triangles_, sizeof(num_triangles_), 1) != 1)
return false;
if (!triangles_.Serialize(fp)) return false;
return true;
}
bool DeSerialize(TFile* fp) {
if (fp->FReadEndian(&num_squares_, sizeof(num_squares_), 1) != 1)
return false;
if (!squares_.DeSerialize(fp)) return false;
if (fp->FReadEndian(&num_triangles_, sizeof(num_triangles_), 1) != 1)
return false;
if (!triangles_.DeSerialize(fp)) return false;
return true;
}
bool SerializeBigEndian(TFile* fp) {
ReverseN(&num_squares_, sizeof(num_squares_));
if (fp->FWrite(&num_squares_, sizeof(num_squares_), 1) != 1) return false;
// Write an additional reversed size before the vector, which will get
// used as its size on reading.
if (fp->FWrite(&num_squares_, sizeof(num_squares_), 1) != 1) return false;
for (int i = 0; i < squares_.size(); ++i)
ReverseN(&squares_[i], sizeof(squares_[i]));
if (!squares_.Serialize(fp)) return false;
ReverseN(&num_triangles_, sizeof(num_triangles_));
if (fp->FWrite(&num_triangles_, sizeof(num_triangles_), 1) != 1)
return false;
if (fp->FWrite(&num_triangles_, sizeof(num_triangles_), 1) != 1)
return false;
for (int i = 0; i < triangles_.size(); ++i)
ReverseN(&triangles_[i], sizeof(triangles_[i]));
return triangles_.Serialize(fp);
}
bool DeSerializeBigEndian(TFile* fp) {
if (fp->FReadEndian(&num_squares_, sizeof(num_squares_), 1) != 1)
return false;
if (!squares_.DeSerialize(fp)) return false;
// The first element is the size that was written, so we will delete it
// and read the last element separately.
int last_element;
if (fp->FReadEndian(&last_element, sizeof(last_element), 1) != 1)
return false;
squares_.remove(0);
squares_.push_back(last_element);
if (fp->FReadEndian(&num_triangles_, sizeof(num_triangles_), 1) != 1)
return false;
if (!triangles_.DeSerialize(fp)) return false;
if (fp->FReadEndian(&last_element, sizeof(last_element), 1) != 1)
return false;
triangles_.remove(0);
triangles_.push_back(last_element);
return true;
}
private:
GenericVector<int> squares_;
int num_squares_;
GenericVector<int> triangles_;
int num_triangles_;
};
};
TEST_F(TfileTest, Serialize) {
// This test verifies that Tfile can serialize a class.
MathData m1;
m1.Setup();
GenericVector<char> data;
TFile fpw;
fpw.OpenWrite(&data);
EXPECT_TRUE(m1.Serialize(&fpw));
TFile fpr;
EXPECT_TRUE(fpr.Open(&data[0], data.size()));
MathData m2;
EXPECT_TRUE(m2.DeSerialize(&fpr));
m1.ExpectEq(m2);
MathData m3;
EXPECT_FALSE(m3.DeSerialize(&fpr));
fpr.Rewind();
EXPECT_TRUE(m3.DeSerialize(&fpr));
m1.ExpectEq(m3);
}
TEST_F(TfileTest, FGets) {
// This test verifies that Tfile can interleave FGets with binary data.
MathData m1;
std::string line_str = "This is a textline with a newline\n";
m1.Setup();
GenericVector<char> data;
TFile fpw;
fpw.OpenWrite(&data);
EXPECT_TRUE(m1.Serialize(&fpw));
EXPECT_EQ(1, fpw.FWrite(line_str.data(), line_str.size(), 1));
EXPECT_TRUE(m1.Serialize(&fpw));
// Now get back the 2 copies of m1 with the line in between.
TFile fpr;
EXPECT_TRUE(fpr.Open(&data[0], data.size()));
MathData m2;
EXPECT_TRUE(m2.DeSerialize(&fpr));
m1.ExpectEq(m2);
const int kBufsize = 1024;
char buffer[kBufsize + 1];
EXPECT_EQ(buffer, fpr.FGets(buffer, kBufsize));
EXPECT_STREQ(line_str.c_str(), buffer);
MathData m3;
EXPECT_TRUE(m3.DeSerialize(&fpr));
m1.ExpectEq(m3);
}
TEST_F(TfileTest, BigEndian) {
// This test verifies that Tfile can auto-reverse big-endian data.
MathData m1;
m1.Setup();
GenericVector<char> data;
TFile fpw;
fpw.OpenWrite(&data);
EXPECT_TRUE(m1.SerializeBigEndian(&fpw));
TFile fpr;
EXPECT_TRUE(fpr.Open(&data[0], data.size()));
fpr.set_swap(true);
MathData m2;
EXPECT_TRUE(m2.DeSerializeBigEndian(&fpr));
// That serialize was destructive, so test against a fresh MathData.
MathData m3;
m3.Setup();
m3.ExpectEq(m2);
}
} // namespace