1 /** @file
2 
3   A brief file description
4 
5   @section license License
6 
7   Licensed to the Apache Software Foundation (ASF) under one
8   or more contributor license agreements.  See the NOTICE file
9   distributed with this work for additional information
10   regarding copyright ownership.  The ASF licenses this file
11   to you under the Apache License, Version 2.0 (the
12   "License"); you may not use this file except in compliance
13   with the License.  You may obtain a copy of the License at
14 
15       http://www.apache.org/licenses/LICENSE-2.0
16 
17   Unless required by applicable law or agreed to in writing, software
18   distributed under the License is distributed on an "AS IS" BASIS,
19   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20   See the License for the specific language governing permissions and
21   limitations under the License.
22  */
23 
24 #define LARGE_FILE 10 * 1024 * 1024
25 #define SMALL_FILE 10 * 1024
26 
27 #include "main.h"
28 
29 // delete dir
30 Dir dir = {};
31 
32 class CacheAltReadAgain2 : public CacheTestHandler
33 {
34 public:
CacheAltReadAgain2(size_t size,const char * url)35   CacheAltReadAgain2(size_t size, const char *url) : CacheTestHandler()
36   {
37     auto rt = new CacheReadTest(size, this, url);
38 
39     rt->mutex = this->mutex;
40     this->_rt = rt;
41     SET_HANDLER(&CacheAltReadAgain2::start_test);
42   }
43 
44   int
start_test(int event,void * e)45   start_test(int event, void *e)
46   {
47     REQUIRE(event == EVENT_IMMEDIATE);
48     this_ethread()->schedule_imm(this->_rt);
49     return 0;
50   }
51 
52   void
handle_cache_event(int event,CacheTestBase * base)53   handle_cache_event(int event, CacheTestBase *base) override
54   {
55     switch (event) {
56     case CACHE_EVENT_OPEN_READ:
57       base->do_io_read();
58       validate_content_type(base);
59       break;
60     case VC_EVENT_READ_READY:
61       base->reenable();
62       break;
63     case VC_EVENT_READ_COMPLETE:
64       base->close();
65       delete this;
66       break;
67     default:
68       REQUIRE(false);
69       break;
70     }
71   }
72 
73   void
validate_content_type(CacheTestBase * base)74   validate_content_type(CacheTestBase *base)
75   {
76     auto rt = dynamic_cast<CacheReadTest *>(base);
77     REQUIRE(rt);
78     MIMEField *field = rt->read_http_info->m_alt->m_response_hdr.field_find(MIME_FIELD_CONTENT_TYPE, MIME_LEN_CONTENT_TYPE);
79     REQUIRE(field);
80     int len;
81     const char *value = field->value_get(&len);
82     REQUIRE(memcmp(value, "text/html;charset=utf-8", len) == 0);
83   }
84 };
85 
86 class CacheAltReadAgain : public CacheTestHandler
87 {
88 public:
CacheAltReadAgain(size_t size,const char * url)89   CacheAltReadAgain(size_t size, const char *url) : CacheTestHandler()
90   {
91     auto rt = new CacheReadTest(size, this, url);
92 
93     rt->mutex = this->mutex;
94 
95     rt->info.destroy();
96 
97     rt->info.create();
98     build_hdrs(rt->info, url, "application/x-javascript");
99 
100     this->_rt = rt;
101 
102     SET_HANDLER(&CacheAltReadAgain::start_test);
103   }
104 
105   int
start_test(int event,void * e)106   start_test(int event, void *e)
107   {
108     REQUIRE(event == EVENT_IMMEDIATE);
109     this_ethread()->schedule_imm(this->_rt);
110     return 0;
111   }
112 
113   void
handle_cache_event(int event,CacheTestBase * base)114   handle_cache_event(int event, CacheTestBase *base) override
115   {
116     switch (event) {
117     case CACHE_EVENT_OPEN_READ_FAILED:
118       delete this;
119       break;
120     default:
121       REQUIRE(false);
122       break;
123     }
124   }
125 
126   void
validate_content_type(CacheTestBase * base)127   validate_content_type(CacheTestBase *base)
128   {
129     auto rt = dynamic_cast<CacheReadTest *>(base);
130     REQUIRE(rt);
131     MIMEField *field = rt->read_http_info->m_alt->m_response_hdr.field_find(MIME_FIELD_CONTENT_TYPE, MIME_LEN_CONTENT_TYPE);
132     REQUIRE(field);
133     int len;
134     const char *value = field->value_get(&len);
135     REQUIRE(memcmp(value, "text/html;charset=utf-8", len) == 0);
136   }
137 };
138 
139 class CacheAltTest_L_to_S_remove_S : public CacheTestHandler
140 {
141 public:
CacheAltTest_L_to_S_remove_S(size_t size,const char * url)142   CacheAltTest_L_to_S_remove_S(size_t size, const char *url) : CacheTestHandler()
143   {
144     auto rt = new CacheReadTest(size, this, url);
145     auto wt = new CacheWriteTest(size, this, url);
146 
147     rt->info.destroy();
148     wt->info.destroy();
149 
150     rt->info.create();
151     wt->info.create();
152 
153     build_hdrs(rt->info, url, "application/x-javascript");
154     build_hdrs(wt->info, url, "application/x-javascript");
155 
156     this->_rt = rt;
157     this->_wt = wt;
158 
159     this->_rt->mutex = this->mutex;
160     this->_wt->mutex = this->mutex;
161 
162     SET_HANDLER(&CacheAltTest_L_to_S_remove_S::start_test);
163   }
164 
165   int
start_test(int event,void * e)166   start_test(int event, void *e)
167   {
168     REQUIRE(event == EVENT_IMMEDIATE);
169     this_ethread()->schedule_imm(this->_wt);
170     return 0;
171   }
172 
173   void
handle_cache_event(int event,CacheTestBase * base)174   handle_cache_event(int event, CacheTestBase *base) override
175   {
176     switch (event) {
177     case CACHE_EVENT_OPEN_WRITE:
178       base->do_io_write();
179       break;
180     case VC_EVENT_WRITE_READY:
181       base->reenable();
182       break;
183     case VC_EVENT_WRITE_COMPLETE:
184       this->_wt->close();
185       this->_wt = nullptr;
186       this_ethread()->schedule_imm(this->_rt);
187       break;
188     case CACHE_EVENT_OPEN_READ:
189       base->do_io_read();
190       validate_content_type(base);
191       break;
192     case VC_EVENT_READ_READY:
193       base->reenable();
194       break;
195     case VC_EVENT_READ_COMPLETE:
196       delete_earliest_dir(base->vc);
197       base->close();
198       delete this;
199       break;
200     default:
201       REQUIRE(false);
202       break;
203     }
204   }
205 
206   void
validate_content_type(CacheTestBase * base)207   validate_content_type(CacheTestBase *base)
208   {
209     auto rt = dynamic_cast<CacheReadTest *>(base);
210     REQUIRE(rt);
211     MIMEField *field = rt->read_http_info->m_alt->m_response_hdr.field_find(MIME_FIELD_CONTENT_TYPE, MIME_LEN_CONTENT_TYPE);
212     REQUIRE(field);
213     int len;
214     const char *value = field->value_get(&len);
215     REQUIRE(memcmp(value, "application/x-javascript", len) == 0);
216   }
217 
218   void
delete_earliest_dir(CacheVC * vc)219   delete_earliest_dir(CacheVC *vc)
220   {
221     CacheKey key        = {};
222     Dir *last_collision = nullptr;
223     SCOPED_MUTEX_LOCK(lock, vc->vol->mutex, this->mutex->thread_holding);
224     vc->vector.data[1].alternate.object_key_get(&key);
225     REQUIRE(dir_probe(&key, vc->vol, &dir, &last_collision) != 0);
226     REQUIRE(dir_delete(&key, vc->vol, &dir));
227   }
228 };
229 
230 class CacheAltInit : public CacheInit
231 {
232 public:
CacheAltInit()233   CacheAltInit() {}
234   int
cache_init_success_callback(int event,void * e)235   cache_init_success_callback(int event, void *e) override
236   {
237     CacheTestHandler *h              = new CacheTestHandler(LARGE_FILE, "http://www.scw11.com");
238     CacheAltTest_L_to_S_remove_S *ls = new CacheAltTest_L_to_S_remove_S(SMALL_FILE, "http://www.scw11.com");
239     CacheAltReadAgain *read          = new CacheAltReadAgain(SMALL_FILE, "http://www.scw11.com");
240     CacheAltReadAgain2 *read2        = new CacheAltReadAgain2(LARGE_FILE, "http://www.scw11.com");
241     TerminalTest *tt                 = new TerminalTest;
242 
243     h->add(ls);
244     h->add(read); // read again
245     h->add(read2);
246     h->add(tt);
247     this_ethread()->schedule_imm(h);
248     delete this;
249     return 0;
250   }
251 };
252 
253 TEST_CASE("cache write -> read", "cache")
254 {
255   init_cache(256 * 1024 * 1024);
256   // large write test
257   CacheAltInit *init = new CacheAltInit;
258 
259   this_ethread()->schedule_imm(init);
260   this_thread()->execute();
261 }
262