1 //
2 // Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012
3 // Free Software Foundation, Inc
4 //
5 // This program is free software; you can redistribute it and/or modify
6 // it under the terms of the GNU General Public License as published by
7 // the Free Software Foundation; either version 3 of the License, or
8 // (at your option) any later version.
9 //
10 // This program is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU General Public License for more details.
14 //
15 // You should have received a copy of the GNU General Public License
16 // along with this program; if not, write to the Free Software
17 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18
19 #ifdef HAVE_CONFIG_H
20 #include "gnashconfig.h"
21 #endif
22
23 #ifdef HAVE_DEJAGNU_H
24 #include "dejagnu.h"
25 #endif
26 #include "check.h"
27
28 #include "noseek_fd_adapter.h"
29 #include "IOChannel.h"
30 #include "tu_file.h"
31
32 #include <cstdio>
33 #include <iostream>
34 #include <cassert>
35 #include <memory>
36
37 #include "GnashSystemIOHeaders.h"
38 #include <sys/types.h>
39 #include <sys/stat.h>
40 #include <fcntl.h>
41 #include <string.h>
42 #include <sstream>
43 #include <limits>
44
45 using namespace std;
46
47 #define CHUNK_SIZE 4
48
49 TestState runtest;
50
51 static void
dump_buffer(const char * label,char * buf,ssize_t size,ostream & os)52 dump_buffer(const char* label, char* buf, ssize_t size, ostream& os)
53 {
54 os << label << ":" << endl;
55 for (ssize_t i=0; i<size; i++) {
56 os << '[' << buf[i] << ']';
57 }
58
59 }
60
61
62 static bool
compare_reads(gnash::IOChannel * reader,int fd,const char * first,const char * second)63 compare_reads(gnash::IOChannel* reader, int fd, const char* first, const char* second)
64 {
65 char buf[CHUNK_SIZE];
66 char buf2[CHUNK_SIZE];
67
68 stringstream ss;
69
70
71 size_t consumed = 0;
72
73 for(;;)
74 {
75 ssize_t sz1 = reader->read(buf, CHUNK_SIZE);
76 ssize_t sz2 = read(fd, buf2, CHUNK_SIZE);
77
78 if ( sz1 != sz2 )
79 {
80 ss << "Different read size from " << first
81 << " (" << sz1 << ") and " << second
82 << " (" << sz2 << ") file";
83 runtest.fail(ss.str());
84 dump_buffer("wrapped", buf, sz1, cout);
85 dump_buffer("raw", buf2, sz2, cout);
86 return false;
87 }
88
89 if ( sz1 <= 0 ) {
90 break;
91 }
92
93 if ( memcmp(buf, buf2, sz1) )
94 {
95 ss << "Different read content from " << first
96 << " and " << second << " file";
97 runtest.fail(ss.str());
98 dump_buffer("wrapped", buf, sz1, cout);
99 dump_buffer("raw", buf2, sz2, cout);
100 return false;
101 }
102
103 consumed+=sz1;
104 }
105
106 if ( consumed == 0 )
107 {
108 runtest.fail("No bytes read from either " + string(first) + " or " + string(second) + " file");
109 return false;
110 }
111
112 if ( ! reader->eof() )
113 {
114 ss << "tu_file not at EOF at end of read";
115 runtest.fail(ss.str());
116 return false;
117 }
118
119 ss << "compared " << consumed << " bytes from "
120 << first << " and " << second;
121
122 runtest.pass(ss.str());
123 return true;
124
125
126 return true;
127
128 }
129
130 TRYMAIN(_runtest);
131 int
trymain(int,char **)132 trymain(int /*argc*/, char** /*argv*/)
133 {
134 const char* input = INPUT; // Should be the path to this file
135 const char* cachename = "NoSeekFileTestCache";
136
137 int fd = open(input, O_RDONLY);
138 int raw = open(input, O_RDONLY);
139
140 if (fd < 0 || raw < 0) {
141 runtest.fail("Unable to open input file");
142 }
143
144 dup2(fd, 0);
145 close(fd);
146
147 std::unique_ptr<gnash::IOChannel> reader(gnash::noseek_fd_adapter::make_stream(0, cachename));
148 assert(reader);
149
150 compare_reads(reader.get(), raw, "wrapped", "raw");
151
152 lseek(raw, 0, SEEK_SET);
153 reader->seek(0);
154 compare_reads(reader.get(), raw, "wrapped-rewind", "raw-rewind");
155
156
157 FILE* f = std::fopen(cachename, "r");
158 std::unique_ptr<gnash::IOChannel> orig = gnash::makeFileChannel(f, false);
159 lseek(raw, 0, SEEK_SET);
160 compare_reads(orig.get(), raw, "cache", "raw");
161 close(raw);
162
163
164 if (sizeof(size_t) != sizeof(std::streamoff)) {
165 std::streampos pos = std::numeric_limits<size_t>::max();
166 pos += orig->size() / 2;
167 // Check that seek() handles integer overflow situations gracefully.
168 if (orig->seek(pos)) {
169 runtest.fail("Successfully sought to an invalid position.");
170 } else {
171 runtest.pass("Gracefully handled invalid seek.");
172 }
173 }
174
175
176
177 return 0;
178 }
179
180