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 const size_t headroom = 512;
56 const size_t tailroom = 512;
57 const size_t align_block = 16;
58 const unsigned int buffer_flags = 0;
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 else
86 return 0;
87 }
88
89 private:
91};
92
93inline void verify_eq(const Buffer &b1, const Buffer &b2)
94{
95 ASSERT_EQ(b1, b2) << "decompressed data doesn't match original data";
96}
97
98void test(const std::string &filename,
99 Compress &compressor,
100 Compress &decompressor,
101 const Frame &frame,
102 const size_t block_size,
103 const size_t n_compress,
104 const size_t n_expand_per_compress,
105 size_t &bytes,
106 size_t &compress_bytes)
107{
108 BufferPtr source_data = read_binary(filename);
109 for (size_t offset = 0; offset < source_data->size(); offset += block_size)
110 {
111 const size_t length = std::min(block_size, source_data->size() - offset);
112 BufferAllocated data_seg;
113 frame.prepare(Frame::DECRYPT_WORK, data_seg);
114 data_seg.write(source_data->data_raw() + offset, length);
115 for (size_t compress_iter = 0; compress_iter < n_compress; ++compress_iter)
116 {
117 BufferAllocated data1(data_seg);
118 bytes += data1.size();
119 compressor.compress(data1, true);
120 compress_bytes += data1.size();
121 if (n_expand_per_compress == 1)
122 {
123 decompressor.decompress(data1);
124 verify_eq(data_seg, data1);
125 }
126 else
127 {
128 for (size_t decompress_iter = 0; decompress_iter < n_expand_per_compress; ++decompress_iter)
129 {
130 BufferAllocated data2(data1);
131 decompressor.decompress(data2);
132 verify_eq(data_seg, data2);
133 }
134 }
135 }
136 }
137}
138
139void test_with_corpus(Compress &compressor,
140 Compress &decompressor,
141 const Frame &frame,
142 const size_t block_size,
143 const size_t n_compress,
144 const size_t n_expand_per_compress,
145 size_t &bytes,
146 size_t &compress_bytes)
147{
148 static const std::vector<std::string> filenames = {
149 "comp-testdata/alice29.txt",
150 "comp-testdata/asyoulik.txt",
151 "comp-testdata/cp.html",
152 "comp-testdata/fields.c",
153 "comp-testdata/geo.protodata",
154 "comp-testdata/grammar.lsp",
155 "comp-testdata/house.jpg",
156 "comp-testdata/html",
157 "comp-testdata/html_x_4",
158 "comp-testdata/kennedy.xls",
159 "comp-testdata/kppkn.gtb",
160 "comp-testdata/lcet10.txt",
161 "comp-testdata/mapreduce-osdi-1.pdf",
162 "comp-testdata/plrabn12.txt",
163 "comp-testdata/ptt5",
164 "comp-testdata/sum",
165 "comp-testdata/urls.10K",
166 "comp-testdata/xargs.1",
167 };
168 for (const auto &fn : filenames)
169 {
170 test(std::string(UNITTEST_SOURCE_DIR) + '/' + fn,
171 compressor,
172 decompressor,
173 frame,
174 block_size,
175 n_compress,
176 n_expand_per_compress,
177 bytes,
178 compress_bytes);
179 }
180}
181
182enum class comppair
183{
184 lzo,
185 lzoasym,
186 snappy,
187 lz4
188};
189
190void runTest(comppair alg, bool verbose = false)
191{
195
196
197 Compress::Ptr compress;
198 Compress::Ptr decompress;
199
200 switch (alg)
201 {
202#if defined(HAVE_LZO)
204 compress.reset(new CompressLZO(frame, stats, SUPPORT_SWAP, false));
205 decompress.reset(new CompressLZOAsym(frame, stats, SUPPORT_SWAP, false));
206 break;
207
208 case comppair::lzo:
209 compress.reset(new CompressLZO(frame, stats, SUPPORT_SWAP, false));
210 decompress = compress;
211 break;
212
213#endif
214#if defined(HAVE_LZ4)
215 case comppair::lz4:
216 compress.reset(new CompressLZ4(frame, stats, false));
217 decompress = compress;
218 break;
219#endif
220#if defined(HAVE_SNAPPY)
221 case comppair::snappy:
222 compress.reset(new CompressSnappy(frame, stats, false));
223 decompress = compress;
224 break;
225#endif
226 default:
227 ASSERT_TRUE(false) << "compressor/decompressor pair not supported";
228 }
229 size_t bytes = 0;
230 size_t compress_bytes = 0;
231 test_with_corpus(*compress, *decompress, *frame, BLOCK_SIZE, N_COMPRESS, N_EXPAND, bytes, compress_bytes);
232
233 if (verbose)
234 std::cout << "comp=" << compress->name() << '[' << N_COMPRESS << ']'
235 << " decomp=" << decompress->name() << '[' << N_EXPAND << ']'
236 << " blk=" << BLOCK_SIZE
237 << " bytes=" << bytes
238 << " comp-bytes=" << compress_bytes
239 << " comp-ratio=" << (bytes ? static_cast<float>(compress_bytes) / static_cast<float>(bytes) : 0.0)
240 << std::endl;
241}
242
243namespace unittests {
244#if defined(HAVE_SNAPPY)
245TEST(Compression, snappy)
246{
248}
249#endif
250#if defined(HAVE_LZO)
251TEST(Compression, lzo)
252{
254}
255
256TEST(Compression, lzoasym)
257{
259}
260#endif
261#if defined(HAVE_LZ4)
262TEST(Compression, lz4)
263{
265}
266#endif
267} // 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:90
count_t get_error_count(const Error::Type type) const
Definition test_comp.cpp:81
RCPtr< MySessionStats > Ptr
Definition test_comp.cpp:68
static void init_static()
Definition compress.hpp:523
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:1225
void write(const T *data, const size_t size)
Write data to the buffer.
Definition buffer.hpp:1546
size_t prepare(const unsigned int context, Buffer &buf) const
Definition frame.hpp:266
void standardize_capacity(const unsigned int context_mask)
Definition frame.hpp:297
void reset() noexcept
Points this RCPtr<T> to nullptr safely.
Definition rc.hpp:290
Support deferred server-side state creation when client connects.
Definition ovpncli.cpp:95
BufferPtr read_binary(const std::string &filename, const std::uint64_t max_size=0, const unsigned int buffer_flags=0)
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, cpu_time_pid)
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:93
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