1 /*
2  * Copyright (C) 1996-2021 The Squid Software Foundation and contributors
3  *
4  * Squid software is distributed under GPLv2+ license and includes
5  * contributions from numerous individuals and organizations.
6  * Please see the COPYING and CONTRIBUTORS files for details.
7  */
8 
9 /* DEBUG: section 64    HTTP Range Header */
10 
11 #include "squid.h"
12 #include "fatal.h"
13 #include "HttpHeader.h"
14 #include "HttpHeaderRange.h"
15 
16 /** \todo CLEANUP: This file should be called something_stub.cc */
17 
httpHeaderPutStr(HttpHeader * hdr,Http::HdrType type,const char * str)18 void httpHeaderPutStr(HttpHeader * hdr, Http::HdrType type, const char *str)
19 {
20     fatal ("dummy function\n");
21 }
22 
httpHeaderGetEntry(const HttpHeader * hdr,HttpHeaderPos * pos)23 HttpHeaderEntry *httpHeaderGetEntry(const HttpHeader * hdr, HttpHeaderPos * pos)
24 {
25     fatal ("dummy function\n");
26     return NULL;
27 }
28 
httpHeaderGetList(const HttpHeader * hdr,Http::HdrType id)29 String httpHeaderGetList(const HttpHeader * hdr, Http::HdrType id)
30 {
31     fatal ("dummy function\n");
32     return String();
33 }
34 
httpHeaderHas(const HttpHeader * hdr,Http::HdrType type)35 int httpHeaderHas(const HttpHeader * hdr, Http::HdrType type)
36 {
37     fatal ("dummy function\n");
38     return 0;
39 }
40 
httpHeaderPutContRange(HttpHeader * hdr,const HttpHdrContRange * cr)41 void httpHeaderPutContRange(HttpHeader * hdr, const HttpHdrContRange * cr)
42 {
43     fatal ("dummy function\n");
44 }
45 
46 void
testRangeParser(char const * rangestring)47 testRangeParser(char const *rangestring)
48 {
49     String aString (rangestring);
50     HttpHdrRange *range = HttpHdrRange::ParseCreate (&aString);
51 
52     if (!range)
53         exit (1);
54 
55     HttpHdrRange copy(*range);
56 
57     assert (copy.specs.size() == range->specs.size());
58 
59     HttpHdrRange::iterator pos = range->begin();
60 
61     assert (*pos);
62 
63     delete range;
64 }
65 
66 HttpHdrRange *
rangeFromString(char const * rangestring)67 rangeFromString(char const *rangestring)
68 {
69     String aString (rangestring);
70     HttpHdrRange *range = HttpHdrRange::ParseCreate (&aString);
71 
72     if (!range)
73         exit (1);
74 
75     return range;
76 }
77 
78 void
testRangeIter()79 testRangeIter ()
80 {
81     HttpHdrRange *range=rangeFromString("bytes=0-3, 1-, -2");
82     assert (range->specs.size() == 3);
83     size_t counter = 0;
84     HttpHdrRange::iterator i = range->begin();
85 
86     while (i != range->end()) {
87         ++counter;
88         ++i;
89     }
90 
91     assert (counter == 3);
92     i = range->begin();
93     assert (i - range->begin() == 0);
94     ++i;
95     assert (i - range->begin() == 1);
96     assert (i - range->end() == -2);
97 }
98 
99 void
testRangeCanonization()100 testRangeCanonization()
101 {
102     HttpHdrRange *range=rangeFromString("bytes=0-3, 1-, -2");
103     assert (range->specs.size() == 3);
104 
105     /* 0-3 needs a content length of 4 */
106     /* This passes in the extant code - but should it? */
107 
108     if (!range->canonize(3))
109         exit(1);
110 
111     assert (range->specs.size() == 3);
112 
113     delete range;
114 
115     range=rangeFromString("bytes=0-3, 1-, -2");
116 
117     assert (range->specs.size() == 3);
118 
119     /* 0-3 needs a content length of 4 */
120     if (!range->canonize(4))
121         exit(1);
122 
123     delete range;
124 
125     range=rangeFromString("bytes=3-6");
126 
127     assert (range->specs.size() == 1);
128 
129     /* 3-6 needs a content length of 4 or more */
130     if (range->canonize(3))
131         exit(1);
132 
133     delete range;
134 
135     range=rangeFromString("bytes=3-6");
136 
137     assert (range->specs.size() == 1);
138 
139     /* 3-6 needs a content length of 4 or more */
140     if (!range->canonize(4))
141         exit(1);
142 
143     delete range;
144 
145     range=rangeFromString("bytes=1-1,2-3");
146 
147     assert (range->specs.size()== 2);
148 
149     if (!range->canonize(4))
150         exit(1);
151 
152     assert (range->specs.size() == 2);
153 
154     delete range;
155 }
156 
157 int
main(int argc,char ** argv)158 main(int argc, char **argv)
159 {
160     try {
161         Mem::Init();
162         /* enable for debugging to console */
163         //    _db_init (NULL, NULL);
164         //    Debug::Levels[64] = 9;
165         testRangeParser("bytes=0-3");
166         testRangeParser("bytes=-3");
167         testRangeParser("bytes=1-");
168         testRangeParser("bytes=0-3, 1-, -2");
169         testRangeIter();
170         testRangeCanonization();
171     } catch (const std::exception &e) {
172         printf("Error: dying from an unhandled exception: %s\n", e.what());
173         return 1;
174     } catch (...) {
175         printf("Error: dying from an unhandled exception.\n");
176         return 1;
177     }
178     return 0;
179 }
180 
181