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 class CacheAltReadAgain : public CacheTestHandler
30 {
31 public:
CacheAltReadAgain(size_t size,const char * url)32   CacheAltReadAgain(size_t size, const char *url) : CacheTestHandler()
33   {
34     this->_rt        = new CacheReadTest(size, this, url);
35     this->_rt->mutex = this->mutex;
36 
37     SET_HANDLER(&CacheAltReadAgain::start_test);
38   }
39 
40   int
start_test(int event,void * e)41   start_test(int event, void *e)
42   {
43     REQUIRE(event == EVENT_IMMEDIATE);
44     this_ethread()->schedule_imm(this->_rt);
45     return 0;
46   }
47 
48   void
handle_cache_event(int event,CacheTestBase * base)49   handle_cache_event(int event, CacheTestBase *base) override
50   {
51     switch (event) {
52     case CACHE_EVENT_OPEN_READ:
53       base->do_io_read();
54       validate_content_type(base);
55       break;
56     case VC_EVENT_READ_READY:
57       base->reenable();
58       break;
59     case VC_EVENT_READ_COMPLETE:
60       base->close();
61       delete this;
62       break;
63     default:
64       REQUIRE(false);
65       break;
66     }
67   }
68 
69   void
validate_content_type(CacheTestBase * base)70   validate_content_type(CacheTestBase *base)
71   {
72     auto rt = dynamic_cast<CacheReadTest *>(base);
73     REQUIRE(rt);
74     MIMEField *field = rt->read_http_info->m_alt->m_response_hdr.field_find(MIME_FIELD_CONTENT_TYPE, MIME_LEN_CONTENT_TYPE);
75     REQUIRE(field);
76     int len;
77     const char *value = field->value_get(&len);
78     REQUIRE(memcmp(value, "text/html;charset=utf-8", len) == 0);
79   }
80 };
81 
82 class CacheAltTest_L_to_S : public CacheTestHandler
83 {
84 public:
CacheAltTest_L_to_S(size_t size,const char * url)85   CacheAltTest_L_to_S(size_t size, const char *url) : CacheTestHandler()
86   {
87     auto rt = new CacheReadTest(size, this, url);
88     auto wt = new CacheWriteTest(size, this, url);
89 
90     rt->info.destroy();
91     wt->info.destroy();
92 
93     rt->info.create();
94     wt->info.create();
95 
96     build_hdrs(rt->info, url, "application/x-javascript");
97     build_hdrs(wt->info, url, "application/x-javascript");
98 
99     this->_rt = rt;
100     this->_wt = wt;
101 
102     this->_rt->mutex = this->mutex;
103     this->_wt->mutex = this->mutex;
104 
105     SET_HANDLER(&CacheAltTest_L_to_S::start_test);
106   }
107 
108   int
start_test(int event,void * e)109   start_test(int event, void *e)
110   {
111     REQUIRE(event == EVENT_IMMEDIATE);
112     this_ethread()->schedule_imm(this->_wt);
113     return 0;
114   }
115 
116   void
handle_cache_event(int event,CacheTestBase * base)117   handle_cache_event(int event, CacheTestBase *base) override
118   {
119     switch (event) {
120     case CACHE_EVENT_OPEN_WRITE:
121       base->do_io_write();
122       break;
123     case VC_EVENT_WRITE_READY:
124       base->reenable();
125       break;
126     case VC_EVENT_WRITE_COMPLETE:
127       this->_wt->close();
128       this->_wt = nullptr;
129       this_ethread()->schedule_imm(this->_rt);
130       break;
131     case CACHE_EVENT_OPEN_READ:
132       base->do_io_read();
133       validate_content_type(base);
134       break;
135     case VC_EVENT_READ_READY:
136       base->reenable();
137       break;
138     case VC_EVENT_READ_COMPLETE:
139       base->close();
140       delete this;
141       break;
142     default:
143       REQUIRE(false);
144       break;
145     }
146   }
147 
148 private:
149   void
validate_content_type(CacheTestBase * base)150   validate_content_type(CacheTestBase *base)
151   {
152     auto rt = dynamic_cast<CacheReadTest *>(base);
153     REQUIRE(rt);
154     MIMEField *field = rt->read_http_info->m_alt->m_response_hdr.field_find(MIME_FIELD_CONTENT_TYPE, MIME_LEN_CONTENT_TYPE);
155     REQUIRE(field);
156     int len;
157     const char *value = field->value_get(&len);
158     REQUIRE(memcmp(value, "application/x-javascript", len) == 0);
159   }
160 };
161 
162 class CacheAltInit : public CacheInit
163 {
164 public:
CacheAltInit()165   CacheAltInit() {}
166   int
cache_init_success_callback(int event,void * e)167   cache_init_success_callback(int event, void *e) override
168   {
169     CacheTestHandler *h     = new CacheTestHandler(SMALL_FILE, "http://www.scw11.com");
170     CacheAltTest_L_to_S *ls = new CacheAltTest_L_to_S(LARGE_FILE, "http://www.scw11.com");
171     CacheAltReadAgain *read = new CacheAltReadAgain(SMALL_FILE, "http://www.scw11.com");
172     TerminalTest *tt        = new TerminalTest;
173 
174     h->add(ls);
175     h->add(read); // read again
176     h->add(tt);
177     this_ethread()->schedule_imm(h);
178     delete this;
179     return 0;
180   }
181 };
182 
183 TEST_CASE("cache write -> read", "cache")
184 {
185   init_cache(256 * 1024 * 1024);
186   // large write test
187   CacheAltInit *init = new CacheAltInit;
188 
189   this_ethread()->schedule_imm(init);
190   this_thread()->execute();
191 }
192