1// Copyright 2010 Google Inc.
2// All rights reserved.
3//
4// Redistribution and use in source and binary forms, with or without
5// modification, are permitted provided that the following conditions are
6// met:
7//
8// * Redistributions of source code must retain the above copyright
9//   notice, this list of conditions and the following disclaimer.
10// * Redistributions in binary form must reproduce the above copyright
11//   notice, this list of conditions and the following disclaimer in the
12//   documentation and/or other materials provided with the distribution.
13// * Neither the name of Google Inc. nor the names of its contributors
14//   may be used to endorse or promote products derived from this software
15//   without specific prior written permission.
16//
17// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
29#include "utils/process/systembuf.hpp"
30
31extern "C" {
32#include <sys/stat.h>
33
34#include <fcntl.h>
35#include <unistd.h>
36}
37
38#include <fstream>
39
40#include <atf-c++.hpp>
41
42using utils::process::systembuf;
43
44
45static void
46check_data(std::istream& is, std::size_t length)
47{
48    char ch = 'A', chr;
49    std::size_t cnt = 0;
50    while (is >> chr) {
51        ATF_REQUIRE_EQ(ch, chr);
52        if (ch == 'Z')
53            ch = 'A';
54        else
55            ch++;
56        cnt++;
57    }
58    ATF_REQUIRE_EQ(cnt, length);
59}
60
61
62static void
63write_data(std::ostream& os, std::size_t length)
64{
65    char ch = 'A';
66    for (std::size_t i = 0; i < length; i++) {
67        os << ch;
68        if (ch == 'Z')
69            ch = 'A';
70        else
71            ch++;
72    }
73    os.flush();
74}
75
76
77static void
78test_read(std::size_t length, std::size_t bufsize)
79{
80    std::ofstream f("test_read.txt");
81    write_data(f, length);
82    f.close();
83
84    int fd = ::open("test_read.txt", O_RDONLY);
85    ATF_REQUIRE(fd != -1);
86    systembuf sb(fd, bufsize);
87    std::istream is(&sb);
88    check_data(is, length);
89    ::close(fd);
90    ::unlink("test_read.txt");
91}
92
93
94static void
95test_write(std::size_t length, std::size_t bufsize)
96{
97    int fd = ::open("test_write.txt", O_WRONLY | O_CREAT | O_TRUNC,
98                    S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
99    ATF_REQUIRE(fd != -1);
100    systembuf sb(fd, bufsize);
101    std::ostream os(&sb);
102    write_data(os, length);
103    ::close(fd);
104
105    std::ifstream is("test_write.txt");
106    check_data(is, length);
107    is.close();
108    ::unlink("test_write.txt");
109}
110
111
112ATF_TEST_CASE(short_read);
113ATF_TEST_CASE_HEAD(short_read)
114{
115    set_md_var("descr", "Tests that a short read (one that fits in the "
116               "internal buffer) works when using systembuf");
117}
118ATF_TEST_CASE_BODY(short_read)
119{
120    test_read(64, 1024);
121}
122
123
124ATF_TEST_CASE(long_read);
125ATF_TEST_CASE_HEAD(long_read)
126{
127    set_md_var("descr", "Tests that a long read (one that does not fit in "
128               "the internal buffer) works when using systembuf");
129}
130ATF_TEST_CASE_BODY(long_read)
131{
132    test_read(64 * 1024, 1024);
133}
134
135
136ATF_TEST_CASE(short_write);
137ATF_TEST_CASE_HEAD(short_write)
138{
139    set_md_var("descr", "Tests that a short write (one that fits in the "
140               "internal buffer) works when using systembuf");
141}
142ATF_TEST_CASE_BODY(short_write)
143{
144    test_write(64, 1024);
145}
146
147
148ATF_TEST_CASE(long_write);
149ATF_TEST_CASE_HEAD(long_write)
150{
151    set_md_var("descr", "Tests that a long write (one that does not fit "
152               "in the internal buffer) works when using systembuf");
153}
154ATF_TEST_CASE_BODY(long_write)
155{
156    test_write(64 * 1024, 1024);
157}
158
159
160ATF_INIT_TEST_CASES(tcs)
161{
162    ATF_ADD_TEST_CASE(tcs, short_read);
163    ATF_ADD_TEST_CASE(tcs, long_read);
164    ATF_ADD_TEST_CASE(tcs, short_write);
165    ATF_ADD_TEST_CASE(tcs, long_write);
166}
167