OpenVPN 3 Core Library
Loading...
Searching...
No Matches
test_comp.cpp
Go to the documentation of this file.
1// OpenVPN -- An application to securely tunnel IP networks
2// over a single port, with support for SSL/TLS-based
3// session authentication and key exchange,
4// packet encryption, packet authentication, and
5// packet compression.
6//
7// Copyright (C) 2012- OpenVPN Inc.
8//
9// SPDX-License-Identifier: MPL-2.0 OR AGPL-3.0-only WITH openvpn3-openssl-exception
10//
11
12#include <iostream>
13#include <algorithm> // for std::min
14
15#ifndef BLOCK_SIZE
16#define BLOCK_SIZE 1500
17#endif
18
19#ifndef N_COMPRESS
20#define N_COMPRESS 1
21#endif
22
29#ifndef N_EXPAND
30#define N_EXPAND 1
31#endif
32
33#ifndef SUPPORT_SWAP
34#define SUPPORT_SWAP false
35#endif
36
37// other defines:
38// must define TEST_x to define compressor/decompressor pair
39// OPENVPN_DEBUG_COMPRESS = 0|1|2
40
41#include "test_common.hpp"
42
50
51using namespace openvpn;
52
53Frame::Ptr frame_init(const size_t payload)
54{
55 constexpr size_t headroom = 512;
56 constexpr size_t tailroom = 512;
57 constexpr size_t align_block = 16;
58 constexpr BufferFlags buffer_flags = BufAllocFlags::NO_FLAGS;
59
60 Frame::Ptr frame(new Frame(Frame::Context(headroom, payload, tailroom, 0, align_block, buffer_flags)));
61 frame->standardize_capacity(~0);
62 return frame;
63}
64
65class MySessionStats : public SessionStats
66{
67 public:
69
71 {
72 std::memset(errors, 0, sizeof(errors));
73 }
74
75 void error(const size_t err_type, const std::string *text = NULL) override
76 {
77 if (err_type < Error::N_ERRORS)
78 ++errors[err_type];
79 }
80
82 {
83 if (type < Error::N_ERRORS)
84 return errors[type];
85 return 0;
86 }
87
88 private:
90};
91
92inline void verify_eq(const Buffer &b1, const Buffer &b2)
93{
94 ASSERT_EQ(b1, b2) << "decompressed data doesn't match original data";
95}
96
97void test(const std::string &filename,
98 Compress &compressor,
99 Compress &decompressor,
100 const Frame &frame,
101 const size_t block_size,
102 const size_t n_compress,
103 const size_t n_expand_per_compress,
104 size_t &bytes,
105 size_t &compress_bytes)
106{
107 BufferPtr source_data = read_binary(filename);
108 for (size_t offset = 0; offset < source_data->size(); offset += block_size)
109 {
110 const size_t length = std::min(block_size, source_data->size() - offset);
111 BufferAllocated data_seg;
112 frame.prepare(Frame::DECRYPT_WORK, data_seg);
113 data_seg.write(source_data->data_raw() + offset, length);
114 for (size_t compress_iter = 0; compress_iter < n_compress; ++compress_iter)
115 {
116 BufferAllocated data1(data_seg);
117 bytes += data1.size();
118 compressor.compress(data1, true);
119 compress_bytes += data1.size();
120 if (n_expand_per_compress == 1)
121 {
122 decompressor.decompress(data1);
123 verify_eq(data_seg, data1);
124 }
125 else
126 {
127 for (size_t decompress_iter = 0; decompress_iter < n_expand_per_compress; ++decompress_iter)
128 {
129 BufferAllocated data2(data1);
130 decompressor.decompress(data2);
131 verify_eq(data_seg, data2);
132 }
133 }
134 }
135 }
136}
137
138void test_with_corpus(Compress &compressor,
139 Compress &decompressor,
140 const Frame &frame,
141 const size_t block_size,
142 const size_t n_compress,
143 const size_t n_expand_per_compress,
144 size_t &bytes,
145 size_t &compress_bytes)
146{
147 static const std::vector<std::string> filenames = {
148 "comp-testdata/alice29.txt",
149 "comp-testdata/asyoulik.txt",
150 "comp-testdata/cp.html",
151 "comp-testdata/fields.c",
152 "comp-testdata/geo.protodata",
153 "comp-testdata/grammar.lsp",
154 "comp-testdata/house.jpg",
155 "comp-testdata/html",
156 "comp-testdata/html_x_4",
157 "comp-testdata/kennedy.xls",
158 "comp-testdata/kppkn.gtb",
159 "comp-testdata/lcet10.txt",
160 "comp-testdata/mapreduce-osdi-1.pdf",
161 "comp-testdata/plrabn12.txt",
162 "comp-testdata/ptt5",
163 "comp-testdata/sum",
164 "comp-testdata/urls.10K",
165 "comp-testdata/xargs.1",
166 };
167 for (const auto &fn : filenames)
168 {
169 test(std::string(UNITTEST_SOURCE_DIR) + '/' + fn,
170 compressor,
171 decompressor,
172 frame,
173 block_size,
174 n_compress,
175 n_expand_per_compress,
176 bytes,
177 compress_bytes);
178 }
179}
180
181enum class comppair
182{
183 lzo,
184 lzoasym,
185 snappy,
186 lz4
187};
188
189void runTest(comppair alg, bool verbose = false)
190{
194
195
196 Compress::Ptr compress;
197 Compress::Ptr decompress;
198
199 switch (alg)
200 {
201#ifdef HAVE_LZO
203 compress.reset(new CompressLZO(frame, stats, SUPPORT_SWAP, false));
204 decompress.reset(new CompressLZOAsym(frame, stats, SUPPORT_SWAP, false));
205 break;
206
207 case comppair::lzo:
208 compress.reset(new CompressLZO(frame, stats, SUPPORT_SWAP, false));
209 decompress = compress;
210 break;
211
212#endif
213#ifdef HAVE_LZ4
214 case comppair::lz4:
215 compress.reset(new CompressLZ4(frame, stats, false));
216 decompress = compress;
217 break;
218#endif
219#ifdef HAVE_SNAPPY
220 case comppair::snappy:
221 compress.reset(new CompressSnappy(frame, stats, false));
222 decompress = compress;
223 break;
224#endif
225 default:
226 ASSERT_TRUE(false) << "compressor/decompressor pair not supported";
227 }
228 size_t bytes = 0;
229 size_t compress_bytes = 0;
230 test_with_corpus(*compress, *decompress, *frame, BLOCK_SIZE, N_COMPRESS, N_EXPAND, bytes, compress_bytes);
231
232 if (verbose)
233 std::cout << "comp=" << compress->name() << '[' << N_COMPRESS << ']'
234 << " decomp=" << decompress->name() << '[' << N_EXPAND << ']'
235 << " blk=" << BLOCK_SIZE
236 << " bytes=" << bytes
237 << " comp-bytes=" << compress_bytes
238 << " comp-ratio=" << (bytes ? static_cast<float>(compress_bytes) / static_cast<float>(bytes) : 0.0)
239 << '\n';
240}
241
242namespace unittests {
243#ifdef HAVE_SNAPPY
244TEST(Compression, Snappy)
245{
247}
248#endif
249#ifdef HAVE_LZO
250TEST(Compression, Lzo)
251{
253}
254
255TEST(Compression, Lzoasym)
256{
258}
259#endif
260#ifdef HAVE_LZ4
261TEST(Compression, Lz4)
262{
264}
265#endif
266} // namespace unittests
void error(const size_t err_type, const std::string *text=NULL) override
Definition test_comp.cpp:75
count_t errors[Error::N_ERRORS]
Definition test_comp.cpp:89
count_t get_error_count(const Error::Type type) const
Definition test_comp.cpp:81
static void init_static()
Definition compress.hpp:520
virtual void decompress(BufferAllocated &buf)=0
virtual void compress(BufferAllocated &buf, const bool hint)=0
size_t size() const
Returns the size of the buffer in T objects.
Definition buffer.hpp:1241
void write(const T *data, const size_t size)
Write data to the buffer.
Definition buffer.hpp:1560
size_t prepare(const unsigned int context, Buffer &buf) const
Definition frame.hpp:263
void standardize_capacity(const unsigned int context_mask)
Definition frame.hpp:294
void reset() noexcept
Points this RCPtr<T> to nullptr safely.
Definition rc.hpp:290
constexpr BufferFlags NO_FLAGS(0U)
no flags set
BufferPtr read_binary(const std::string &filename, const std::uint64_t max_size=0, const BufferFlags buffer_flags=BufAllocFlags::NO_FLAGS)
Definition file.hpp:56
Frame::Ptr frame_init(const bool align_adjust_3_1, const size_t tun_mtu_max, const size_t control_channel_payload, const bool verbose)
long long count_t
Definition count.hpp:16
TEST(CPUTime, CpuTimePid)
void test_with_corpus(Compress &compressor, Compress &decompressor, const Frame &frame, const size_t block_size, const size_t n_compress, const size_t n_expand_per_compress, size_t &bytes, size_t &compress_bytes)
void verify_eq(const Buffer &b1, const Buffer &b2)
Definition test_comp.cpp:92
void runTest(comppair alg, bool verbose=false)
comppair
#define N_EXPAND
Definition test_comp.cpp:30
#define N_COMPRESS
Definition test_comp.cpp:20
#define SUPPORT_SWAP
Definition test_comp.cpp:34
#define BLOCK_SIZE
Definition test_comp.cpp:16
static bool verbose
Definition test_ip.cpp:31
void test()
Definition test_rc.cpp:80