|
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
|
2 /* This Source Code Form is subject to the terms of the Mozilla Public |
|
3 * License, v. 2.0. If a copy of the MPL was not distributed with this |
|
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
|
5 |
|
6 #include <stdio.h> |
|
7 |
|
8 #include "nsIServiceManager.h" |
|
9 #include "nsIEventQueueService.h" |
|
10 #include "nsIOutputStream.h" |
|
11 #include "nsIStreamListener.h" |
|
12 #include "nsITransport.h" |
|
13 #include "nsIInputStream.h" |
|
14 #include "nsIOutputStream.h" |
|
15 #include "nsCOMPtr.h" |
|
16 #include "plstr.h" |
|
17 #include "prprf.h" |
|
18 #include <algorithm> |
|
19 |
|
20 #ifndef USE_CREATE_INSTANCE |
|
21 #include "nsICacheService.h" |
|
22 #include "nsICacheSession.h" |
|
23 #include "nsICacheEntryDescriptor.h" |
|
24 #include "nsNetCID.h" |
|
25 static NS_DEFINE_CID(kCacheServiceCID, NS_CACHESERVICE_CID); |
|
26 static nsICacheSession *session = nullptr; |
|
27 static nsICacheEntryDescriptor *desc = nullptr; |
|
28 #endif |
|
29 |
|
30 /** |
|
31 * This test program exercises the memory cache's nsITransport implementation. |
|
32 * |
|
33 * This test program loads a file into the memory cache (using OpenOutputStream), |
|
34 * and then reads the file back out (using AsyncRead). The data read from the |
|
35 * memory cache is written to a new file (with .out added as a suffix to the file |
|
36 * name). |
|
37 */ |
|
38 |
|
39 static NS_DEFINE_CID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID); |
|
40 static nsIEventQueue *gEventQ = nullptr; |
|
41 |
|
42 class TestListener : public nsIStreamListener |
|
43 { |
|
44 public: |
|
45 NS_DECL_ISUPPORTS |
|
46 NS_DECL_NSISTREAMLISTENER |
|
47 NS_DECL_NSIREQUESTOBSERVER |
|
48 |
|
49 TestListener(char *); |
|
50 virtual ~TestListener(); |
|
51 |
|
52 private: |
|
53 char *mFilename; |
|
54 FILE *mFile; |
|
55 }; |
|
56 |
|
57 NS_IMPL_ISUPPORTS(TestListener, |
|
58 nsIStreamListener, |
|
59 nsIRequestObserver) |
|
60 |
|
61 TestListener::TestListener(char *filename) |
|
62 : mFilename(filename) |
|
63 , mFile(nullptr) |
|
64 { |
|
65 } |
|
66 |
|
67 TestListener::~TestListener() |
|
68 { |
|
69 } |
|
70 |
|
71 NS_IMETHODIMP |
|
72 TestListener::OnStartRequest(nsIRequest *req, nsISupports *ctx) |
|
73 { |
|
74 printf("OnStartRequest\n"); |
|
75 |
|
76 mFile = fopen(mFilename, "w"); |
|
77 if (!mFile) |
|
78 return NS_ERROR_FAILURE; |
|
79 |
|
80 return NS_OK; |
|
81 } |
|
82 |
|
83 NS_IMETHODIMP |
|
84 TestListener::OnStopRequest(nsIRequest *req, nsISupports *ctx, nsresult status) |
|
85 { |
|
86 printf("OnStopRequest: status=%x\n", status); |
|
87 |
|
88 if (mFile) |
|
89 fclose(mFile); |
|
90 |
|
91 return NS_OK; |
|
92 } |
|
93 |
|
94 NS_IMETHODIMP |
|
95 TestListener::OnDataAvailable(nsIRequest *req, nsISupports *ctx, |
|
96 nsIInputStream *is, |
|
97 uint64_t offset, uint32_t count) |
|
98 { |
|
99 printf("OnDataAvailable: offset=%llu count=%u\n", offset, count); |
|
100 |
|
101 if (!mFile) return NS_ERROR_FAILURE; |
|
102 |
|
103 char buf[128]; |
|
104 nsresult rv; |
|
105 uint32_t nread = 0; |
|
106 |
|
107 while (count) { |
|
108 uint32_t amount = std::min<uint32_t>(count, sizeof(buf)); |
|
109 |
|
110 rv = is->Read(buf, amount, &nread); |
|
111 if (NS_FAILED(rv)) return rv; |
|
112 |
|
113 fwrite(buf, nread, 1, mFile); |
|
114 count -= nread; |
|
115 } |
|
116 return NS_OK; |
|
117 } |
|
118 |
|
119 nsresult TestMCTransport(const char *filename) |
|
120 { |
|
121 nsresult rv = NS_OK; |
|
122 nsCOMPtr<nsITransport> transport; |
|
123 |
|
124 #ifdef USE_CREATE_INSTANCE |
|
125 transport = do_CreateInstance( |
|
126 "@mozilla.org/network/memory-cache-transport;1", &rv); |
|
127 if (NS_FAILED(rv)) |
|
128 return rv; |
|
129 #else |
|
130 nsCOMPtr<nsICacheService> serv(do_GetService(kCacheServiceCID, &rv)); |
|
131 if (NS_FAILED(rv)) return rv; |
|
132 |
|
133 rv = serv->CreateSession("TestMCTransport", |
|
134 nsICache::STORE_IN_MEMORY, true, |
|
135 &session); |
|
136 if (NS_FAILED(rv)) return rv; |
|
137 |
|
138 rv = session->OpenCacheEntry(nsDependentCString(filename), |
|
139 nsICache::ACCESS_READ_WRITE, |
|
140 nsICache::BLOCKING, |
|
141 &desc); |
|
142 if (NS_FAILED(rv)) return rv; |
|
143 |
|
144 rv = desc->MarkValid(); |
|
145 if (NS_FAILED(rv)) return rv; |
|
146 |
|
147 rv = desc->GetTransport(getter_AddRefs(transport)); |
|
148 if (NS_FAILED(rv)) return rv; |
|
149 #endif |
|
150 |
|
151 nsCOMPtr<nsIOutputStream> os; |
|
152 rv = transport->OpenOutputStream(0, (uint32_t) -1, 0, getter_AddRefs(os)); |
|
153 if (NS_FAILED(rv)) return rv; |
|
154 |
|
155 char *out = PR_smprintf("%s.out", filename); |
|
156 nsCOMPtr<nsIStreamListener> listener = new TestListener(out); |
|
157 if (!listener) |
|
158 return NS_ERROR_OUT_OF_MEMORY; |
|
159 |
|
160 nsCOMPtr<nsIRequest> req; |
|
161 rv = transport->AsyncRead(listener, nullptr, 0, (uint32_t) -1, 0, getter_AddRefs(req)); |
|
162 if (NS_FAILED(rv)) return rv; |
|
163 |
|
164 FILE *file = fopen(filename, "r"); |
|
165 if (!file) |
|
166 return NS_ERROR_FILE_NOT_FOUND; |
|
167 |
|
168 char buf[256]; |
|
169 uint32_t count, total=0; |
|
170 |
|
171 while ((count = fread(buf, 1, sizeof(buf), file)) > 0) { |
|
172 printf("writing %u bytes\n", count); |
|
173 total += count; |
|
174 rv = os->Write(buf, count, &count); |
|
175 if (NS_FAILED(rv)) return rv; |
|
176 |
|
177 // process an event |
|
178 PLEvent *event = nullptr; |
|
179 gEventQ->GetEvent(&event); |
|
180 if (event) gEventQ->HandleEvent(event); |
|
181 } |
|
182 |
|
183 printf("wrote %u bytes\n", total); |
|
184 |
|
185 return rv; |
|
186 } |
|
187 |
|
188 int main(int argc, char **argv) |
|
189 { |
|
190 nsresult rv; |
|
191 |
|
192 if (argc < 2) { |
|
193 printf("usage: %s filename\n", argv[0]); |
|
194 return -1; |
|
195 } |
|
196 |
|
197 nsCOMPtr<nsIEventQueueService> eqs = |
|
198 do_GetService(kEventQueueServiceCID, &rv); |
|
199 if (NS_FAILED(rv)) { |
|
200 printf("failed to create event queue service: rv=%x\n", rv); |
|
201 return -1; |
|
202 } |
|
203 |
|
204 rv = eqs->CreateMonitoredThreadEventQueue(); |
|
205 if (NS_FAILED(rv)) { |
|
206 printf("failed to create monitored event queue: rv=%x\n", rv); |
|
207 return -1; |
|
208 } |
|
209 |
|
210 rv = eqs->GetThreadEventQueue(NS_CURRENT_THREAD, &gEventQ); |
|
211 if (NS_FAILED(rv)) { |
|
212 printf("failed to get thread event queue: %x\n", rv); |
|
213 return -1; |
|
214 } |
|
215 |
|
216 rv = TestMCTransport(argv[1]); |
|
217 printf("TestMCTransport returned %x\n", rv); |
|
218 |
|
219 gEventQ->ProcessPendingEvents(); |
|
220 |
|
221 #ifndef USE_CREATE_INSTANCE |
|
222 NS_IF_RELEASE(desc); |
|
223 NS_IF_RELEASE(session); |
|
224 #endif |
|
225 return 0; |
|
226 } |