3bc8a281970e6dd4d0100e4d319193232dbec9e8
[libi2ncommon] / test / test_tmpfstream.cpp
1 /** @file
2  *
3  * tests for the module tmpfstream
4  *
5  * (c) Copyright 2010 by Intra2net AG
6  *
7  * info@intra2net.com
8  */
9
10 //#define NOISEDEBUG
11
12 #define BOOST_TEST_DYN_LINK
13 #include <boost/test/unit_test.hpp>
14
15 #include <iostream>
16 #include <filefunc.hxx>
17 #include <tmpfstream.hpp>
18
19 #ifdef NOISEDEBUG
20 #define DOUT(msg) std::cout << msg << std::endl
21 #else
22 #define DOUT(msg) do {} while (0)
23 #endif
24
25 using namespace std;
26 using namespace I2n;
27
28 namespace bio = boost::iostreams;
29
30 BOOST_AUTO_TEST_SUITE(TestTmpfstream)
31
32 BOOST_AUTO_TEST_CASE(Tmpofstream)
33 {
34     tmpofstream tmpf("./tmp.XXXXXX");
35
36     BOOST_CHECK_EQUAL( true, tmpf.is_open() );
37     BOOST_CHECK_EQUAL( false, tmpf.get_tmp_filename().empty() );
38
39     Stat stat(tmpf.get_tmp_filename());
40
41     DOUT("filename : " << tmpf.get_tmp_filename());
42
43     BOOST_CHECK_EQUAL( true, (bool)stat );
44     BOOST_CHECK_EQUAL( true, stat.is_regular_file() );
45
46     tmpf << "hello world" << endl;
47
48     tmpf.close();
49     BOOST_CHECK_EQUAL( false, tmpf.is_open() );
50
51     Stat stat2(tmpf.get_tmp_filename());
52
53     DOUT("stated path: " << stat2.path());
54     DOUT("filesize: " << stat2.size());
55
56     BOOST_CHECK_EQUAL( true, stat2.size() > 0 );
57
58     BOOST_CHECK_EQUAL( true, tmpf.unlink() );
59
60     Stat stat3(tmpf.get_tmp_filename());
61     BOOST_CHECK_EQUAL( false, (bool)stat3 );
62
63
64
65 BOOST_AUTO_TEST_CASE(TmpofstreamUnlink)
66 {
67     tmpofstream tmpf("./tmp.XXXXXX");
68
69     BOOST_CHECK_EQUAL( true, tmpf.is_open() );
70
71     Stat stat(tmpf.get_tmp_filename());
72     BOOST_CHECK_EQUAL( true, (bool)stat );
73     BOOST_CHECK_EQUAL( true, stat.is_regular_file() );
74
75     tmpf << "hello world" << endl;
76
77     // keep open but delete file
78     tmpf.unlink();
79     stat.recheck();
80     BOOST_CHECK_EQUAL( false, (bool)stat );
81
82     // writing to already deleted file
83     // POSIX explicitly allows this
84     tmpf << "hello world" << endl;
85     tmpf.flush();
86     BOOST_CHECK_EQUAL( true, tmpf.good() );
87
88     // file still gone after closing
89     tmpf.close();
90     stat.recheck();
91     BOOST_CHECK_EQUAL( false, (bool)stat );
92
93
94 BOOST_AUTO_TEST_CASE(TmpofstreamMove1)
95 {
96     // just to be sure
97     unlink(".foobar");
98
99     tmpofstream tmpf("./tmp.XXXXXX");
100
101     BOOST_CHECK_EQUAL( true, tmpf.is_open() );
102
103     Stat stat(tmpf.get_tmp_filename());
104     BOOST_CHECK_EQUAL( true, (bool)stat );
105     BOOST_CHECK_EQUAL( true, stat.is_regular_file() );
106
107     tmpf << "hello world" << endl;
108     BOOST_CHECK_EQUAL( true, tmpf.sync() );
109
110     BOOST_CHECK_EQUAL( true, tmpf.move(".foobar",false) );
111
112     stat.recheck();
113     BOOST_CHECK_EQUAL( false, (bool)stat );
114
115     Stat stat2(".foobar");
116     BOOST_CHECK_EQUAL( true, (bool)stat2 );
117
118     tmpf.close();
119
120     stat.recheck();
121     BOOST_CHECK_EQUAL( false, (bool)stat );
122
123     stat2.recheck();
124     BOOST_CHECK_EQUAL( true, (bool)stat2 );
125
126     unlink(".foobar");
127
128
129 BOOST_AUTO_TEST_CASE(TmpofstreamMove2)
130 {
131     // just to be sure
132     unlink(".foobar");
133
134     tmpofstream tmpf("./tmp.XXXXXX");
135
136     BOOST_CHECK_EQUAL( true, tmpf.is_open() );
137
138     Stat stat(tmpf.get_tmp_filename());
139     BOOST_CHECK_EQUAL( true, (bool)stat );
140     BOOST_CHECK_EQUAL( true, stat.is_regular_file() );
141
142     tmpf << "hello world" << endl;
143     tmpf.flush();
144
145     BOOST_CHECK_EQUAL( true, tmpf.move(".foobar",true) );
146
147     stat.recheck();
148     BOOST_CHECK_EQUAL( false, (bool)stat );
149
150     Stat stat2(".foobar");
151     BOOST_CHECK_EQUAL( true, (bool)stat2 );
152
153     tmpf.close();
154
155     stat.recheck();
156     BOOST_CHECK_EQUAL( false, (bool)stat );
157
158     stat2.recheck();
159     BOOST_CHECK_EQUAL( true, (bool)stat2 );
160
161     unlink(".foobar");
162
163
164 BOOST_AUTO_TEST_CASE(TmpofstreamMoveOverwrite)
165 {
166     // prepare other file
167     write_file(".foobar","blah");
168
169     tmpofstream tmpf("./tmp.XXXXXX");
170
171     BOOST_CHECK_EQUAL( true, tmpf.is_open() );
172
173     Stat stat(tmpf.get_tmp_filename());
174     BOOST_CHECK_EQUAL( true, (bool)stat );
175     BOOST_CHECK_EQUAL( true, stat.is_regular_file() );
176
177     tmpf << "hello world" << endl;
178     tmpf.flush();
179
180     // no overwrite fails
181     BOOST_CHECK_EQUAL( false, tmpf.move(".foobar",false) );
182
183     // overwrite succeeds
184     BOOST_CHECK_EQUAL( true, tmpf.move(".foobar",true) );
185
186     stat.recheck();
187     BOOST_CHECK_EQUAL( false, (bool)stat );
188
189     Stat stat2(".foobar");
190     BOOST_CHECK_EQUAL( true, (bool)stat2 );
191
192     tmpf.close();
193
194     unlink(".foobar");
195
196
197 BOOST_AUTO_TEST_CASE(TmpofstreamMoveAfterUnlink)
198 {
199     // just to be sure
200     unlink(".foobar");
201
202     tmpofstream tmpf("./tmp.XXXXXX");
203
204     BOOST_CHECK_EQUAL( true, tmpf.is_open() );
205
206     Stat stat(tmpf.get_tmp_filename());
207     BOOST_CHECK_EQUAL( true, (bool)stat );
208     BOOST_CHECK_EQUAL( true, stat.is_regular_file() );
209
210     tmpf << "hello world" << endl;
211     tmpf.flush();
212
213     BOOST_CHECK_EQUAL( true, tmpf.unlink() );
214
215     BOOST_CHECK_EQUAL( true, tmpf.is_unlinked() );
216
217     BOOST_CHECK_EQUAL( false, tmpf.move(".foobar") );
218
219     unlink(".foobar");
220
221
222 BOOST_AUTO_TEST_CASE(TmpofstreamDoubleMove)
223 {
224     // just to be sure
225     unlink(".foobar");
226     unlink(".foobar2");
227
228     tmpofstream tmpf("./tmp.XXXXXX");
229
230     BOOST_CHECK_EQUAL( true, tmpf.is_open() );
231
232     Stat stat(tmpf.get_tmp_filename());
233     BOOST_CHECK_EQUAL( true, (bool)stat );
234
235     tmpf << "hello world" << endl;
236     tmpf.flush();
237
238     BOOST_CHECK_EQUAL( true, tmpf.move(".foobar") );
239
240     stat.recheck();
241     BOOST_CHECK_EQUAL( false, (bool)stat );
242
243     Stat stat2(".foobar");
244     BOOST_CHECK_EQUAL( true, (bool)stat2 );
245
246     BOOST_CHECK_EQUAL( true, tmpf.move(".foobar2") );
247
248     stat.recheck();
249     BOOST_CHECK_EQUAL( false, (bool)stat );
250
251     stat2.recheck();
252     BOOST_CHECK_EQUAL( false, (bool)stat2 );
253
254     Stat stat3(".foobar2");
255     BOOST_CHECK_EQUAL( true, (bool)stat3 );
256
257     tmpf.unlink();
258
259
260 BOOST_AUTO_TEST_CASE(TmpfstreamReadWrite)
261 {
262     tmpfstream tmpf("./tmp.XXXXXX",std::ios_base::out | std::ios_base::in );
263     BOOST_CHECK_EQUAL( true, tmpf.is_open() );
264
265     tmpf << "hello world" << endl;
266
267     tmpf.seekg(0);
268     string input;
269     getline(tmpf,input);
270
271     BOOST_CHECK_EQUAL( "hello world", input );
272
273     tmpf.unlink();
274     tmpf.close();
275 }
276
277 BOOST_AUTO_TEST_CASE(Tmpfcopystream)
278 {
279     write_file(".foobar","blah");
280
281     tmpfcopystream tmpf(".foobar");
282     BOOST_CHECK_EQUAL( true, tmpf.is_open() );
283
284     tmpf << "hello world";
285     tmpf.flush();
286
287     BOOST_CHECK_EQUAL( "blah", read_file(".foobar") );
288
289     tmpf.close();
290     BOOST_CHECK_EQUAL( false, tmpf.is_open() );
291
292     BOOST_CHECK_EQUAL( "hello world", read_file(".foobar") );
293
294     unlink(".foobar");
295 }
296
297 BOOST_AUTO_TEST_CASE(TmpfcopystreamDestructor)
298 {
299     write_file(".foobar","blah");
300
301     {
302         tmpfcopystream tmpf(".foobar");
303         BOOST_CHECK_EQUAL( true, tmpf.is_open() );
304
305         tmpf << "hello world";
306         tmpf.flush();
307
308         BOOST_CHECK_EQUAL( "blah", read_file(".foobar") );
309     }
310
311     BOOST_CHECK_EQUAL( "hello world", read_file(".foobar") );
312
313     unlink(".foobar");
314 }
315
316 BOOST_AUTO_TEST_CASE(TmpfcopystreamAbort)
317 {
318     write_file(".foobar","blah");
319
320     tmpfcopystream tmpf(".foobar");
321     BOOST_CHECK_EQUAL( true, tmpf.is_open() );
322
323     tmpf << "hello world";
324     tmpf.flush();
325
326     // abort the overwriting, keep the old file
327     tmpf.unlink();
328
329     BOOST_CHECK_EQUAL( "blah", read_file(".foobar") );
330
331     unlink(".foobar");
332 }
333
334 BOOST_AUTO_TEST_CASE(TmpfcopystreamChmod)
335 {
336     write_file(".foobar","blah");
337     I2n::chmod(".foobar",0644);
338     Stat stat_orig(".foobar");
339     BOOST_CHECK_EQUAL( 0644, stat_orig.mode() );
340
341     tmpfcopystream tmpf(".foobar");
342
343     tmpf << "hello world";
344     tmpf.flush();
345
346     tmpf.set_filemode_on_close(0640);
347
348     Stat stat_tmp(tmpf.get_tmp_filename());
349     BOOST_CHECK_EQUAL( 0600, stat_tmp.mode() );
350
351     tmpf.close();
352
353     stat_orig.recheck();
354     BOOST_CHECK_EQUAL( 0640, stat_orig.mode() );
355
356     unlink(".foobar");
357 }
358
359
360 BOOST_AUTO_TEST_SUITE_END()