aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorJustin Clark-Casey (justincc)2014-03-17 20:51:35 +0000
committerJustin Clark-Casey (justincc)2014-03-17 20:51:35 +0000
commitf3e177814a30ee91a2fdd27f2a1aebf06a39cd15 (patch)
treec511df5ec9e48d961241341e30adce3e33eb7ad7
parentImplement osForceBreakAllLinks(). (diff)
downloadopensim-SC_OLD-f3e177814a30ee91a2fdd27f2a1aebf06a39cd15.zip
opensim-SC_OLD-f3e177814a30ee91a2fdd27f2a1aebf06a39cd15.tar.gz
opensim-SC_OLD-f3e177814a30ee91a2fdd27f2a1aebf06a39cd15.tar.bz2
opensim-SC_OLD-f3e177814a30ee91a2fdd27f2a1aebf06a39cd15.tar.xz
Add regression test for http inventory fetch.
Involved some restructuring to allow regression tests to dequeue inventory requests and perform poll responses synchronously rather than async
-rw-r--r--OpenSim/Capabilities/Caps.cs7
-rw-r--r--OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs24
-rw-r--r--OpenSim/Framework/Servers/HttpServer/PollServiceRequestManager.cs175
-rw-r--r--OpenSim/Framework/Servers/Tests/OSHttpTests.cs320
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/Tests/WebFetchInvDescModuleTests.cs158
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/WebFetchInvDescModule.cs43
-rw-r--r--OpenSim/Region/CoreModules/Framework/Caps/CapabilitiesModule.cs4
-rw-r--r--OpenSim/Tests/Common/Mock/TestHttpClientContext.cs110
-rw-r--r--OpenSim/Tests/Common/Mock/TestHttpRequest.cs174
-rw-r--r--OpenSim/Tests/Common/Mock/TestHttpResponse.cs171
-rw-r--r--prebuild.xml3
11 files changed, 783 insertions, 406 deletions
diff --git a/OpenSim/Capabilities/Caps.cs b/OpenSim/Capabilities/Caps.cs
index bbf3b27..049afab 100644
--- a/OpenSim/Capabilities/Caps.cs
+++ b/OpenSim/Capabilities/Caps.cs
@@ -50,8 +50,7 @@ namespace OpenSim.Framework.Capabilities
50 50
51 public class Caps 51 public class Caps
52 { 52 {
53// private static readonly ILog m_log = 53// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
54// LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
55 54
56 private string m_httpListenerHostName; 55 private string m_httpListenerHostName;
57 private uint m_httpListenPort; 56 private uint m_httpListenPort;
@@ -152,6 +151,10 @@ namespace OpenSim.Framework.Capabilities
152 151
153 public void RegisterPollHandler(string capName, PollServiceEventArgs pollServiceHandler) 152 public void RegisterPollHandler(string capName, PollServiceEventArgs pollServiceHandler)
154 { 153 {
154// m_log.DebugFormat(
155// "[CAPS]: Registering handler with name {0}, url {1} for {2}",
156// capName, pollServiceHandler.Url, m_agentID, m_regionName);
157
155 m_pollServiceHandlers.Add(capName, pollServiceHandler); 158 m_pollServiceHandlers.Add(capName, pollServiceHandler);
156 159
157 m_httpListener.AddPollServiceHTTPHandler(pollServiceHandler.Url, pollServiceHandler); 160 m_httpListener.AddPollServiceHTTPHandler(pollServiceHandler.Url, pollServiceHandler);
diff --git a/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs b/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs
index e1ae74e..e243002 100644
--- a/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs
+++ b/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs
@@ -113,7 +113,7 @@ namespace OpenSim.Framework.Servers.HttpServer
113 113
114 protected IPAddress m_listenIPAddress = IPAddress.Any; 114 protected IPAddress m_listenIPAddress = IPAddress.Any;
115 115
116 private PollServiceRequestManager m_PollServiceManager; 116 public PollServiceRequestManager PollServiceRequestManager { get; private set; }
117 117
118 public uint SSLPort 118 public uint SSLPort
119 { 119 {
@@ -374,7 +374,7 @@ namespace OpenSim.Framework.Servers.HttpServer
374 return true; 374 return true;
375 } 375 }
376 376
377 private void OnRequest(object source, RequestEventArgs args) 377 public void OnRequest(object source, RequestEventArgs args)
378 { 378 {
379 RequestNumber++; 379 RequestNumber++;
380 380
@@ -429,7 +429,7 @@ namespace OpenSim.Framework.Servers.HttpServer
429 psEvArgs.Request(psreq.RequestID, keysvals); 429 psEvArgs.Request(psreq.RequestID, keysvals);
430 } 430 }
431 431
432 m_PollServiceManager.Enqueue(psreq); 432 PollServiceRequestManager.Enqueue(psreq);
433 } 433 }
434 else 434 else
435 { 435 {
@@ -1781,10 +1781,17 @@ namespace OpenSim.Framework.Servers.HttpServer
1781 1781
1782 public void Start() 1782 public void Start()
1783 { 1783 {
1784 StartHTTP(); 1784 Start(true);
1785 } 1785 }
1786 1786
1787 private void StartHTTP() 1787 /// <summary>
1788 /// Start the http server
1789 /// </summary>
1790 /// <param name='processPollRequestsAsync'>
1791 /// If true then poll responses are performed asynchronsly.
1792 /// Option exists to allow regression tests to perform processing synchronously.
1793 /// </param>
1794 public void Start(bool performPollResponsesAsync)
1788 { 1795 {
1789 m_log.InfoFormat( 1796 m_log.InfoFormat(
1790 "[BASE HTTP SERVER]: Starting {0} server on port {1}", UseSSL ? "HTTPS" : "HTTP", Port); 1797 "[BASE HTTP SERVER]: Starting {0} server on port {1}", UseSSL ? "HTTPS" : "HTTP", Port);
@@ -1822,8 +1829,9 @@ namespace OpenSim.Framework.Servers.HttpServer
1822 m_httpListener2.Start(64); 1829 m_httpListener2.Start(64);
1823 1830
1824 // Long Poll Service Manager with 3 worker threads a 25 second timeout for no events 1831 // Long Poll Service Manager with 3 worker threads a 25 second timeout for no events
1825 m_PollServiceManager = new PollServiceRequestManager(this, 3, 25000); 1832 PollServiceRequestManager = new PollServiceRequestManager(this, performPollResponsesAsync, 3, 25000);
1826 m_PollServiceManager.Start(); 1833 PollServiceRequestManager.Start();
1834
1827 HTTPDRunning = true; 1835 HTTPDRunning = true;
1828 1836
1829 //HttpListenerContext context; 1837 //HttpListenerContext context;
@@ -1892,7 +1900,7 @@ namespace OpenSim.Framework.Servers.HttpServer
1892 1900
1893 try 1901 try
1894 { 1902 {
1895 m_PollServiceManager.Stop(); 1903 PollServiceRequestManager.Stop();
1896 1904
1897 m_httpListener2.ExceptionThrown -= httpServerException; 1905 m_httpListener2.ExceptionThrown -= httpServerException;
1898 //m_httpListener2.DisconnectHandler = null; 1906 //m_httpListener2.DisconnectHandler = null;
diff --git a/OpenSim/Framework/Servers/HttpServer/PollServiceRequestManager.cs b/OpenSim/Framework/Servers/HttpServer/PollServiceRequestManager.cs
index 6aa5907..456acb0 100644
--- a/OpenSim/Framework/Servers/HttpServer/PollServiceRequestManager.cs
+++ b/OpenSim/Framework/Servers/HttpServer/PollServiceRequestManager.cs
@@ -44,6 +44,20 @@ namespace OpenSim.Framework.Servers.HttpServer
44 { 44 {
45 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 45 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
46 46
47 /// <summary>
48 /// Is the poll service request manager running?
49 /// </summary>
50 /// <remarks>
51 /// Can be running either synchronously or asynchronously
52 /// </remarks>
53 public bool IsRunning { get; private set; }
54
55 /// <summary>
56 /// Is the poll service performing responses asynchronously (with its own threads) or synchronously (via
57 /// external calls)?
58 /// </summary>
59 public bool PerformResponsesAsync { get; private set; }
60
47 private readonly BaseHttpServer m_server; 61 private readonly BaseHttpServer m_server;
48 62
49 private BlockingQueue<PollServiceHttpRequest> m_requests = new BlockingQueue<PollServiceHttpRequest>(); 63 private BlockingQueue<PollServiceHttpRequest> m_requests = new BlockingQueue<PollServiceHttpRequest>();
@@ -52,48 +66,53 @@ namespace OpenSim.Framework.Servers.HttpServer
52 private uint m_WorkerThreadCount = 0; 66 private uint m_WorkerThreadCount = 0;
53 private Thread[] m_workerThreads; 67 private Thread[] m_workerThreads;
54 68
55 private bool m_running = true;
56
57 private SmartThreadPool m_threadPool = new SmartThreadPool(20000, 12, 2); 69 private SmartThreadPool m_threadPool = new SmartThreadPool(20000, 12, 2);
58 70
59// private int m_timeout = 1000; // increase timeout 250; now use the event one 71// private int m_timeout = 1000; // increase timeout 250; now use the event one
60 72
61 public PollServiceRequestManager(BaseHttpServer pSrv, uint pWorkerThreadCount, int pTimeout) 73 public PollServiceRequestManager(
74 BaseHttpServer pSrv, bool performResponsesAsync, uint pWorkerThreadCount, int pTimeout)
62 { 75 {
63 m_server = pSrv; 76 m_server = pSrv;
77 PerformResponsesAsync = performResponsesAsync;
64 m_WorkerThreadCount = pWorkerThreadCount; 78 m_WorkerThreadCount = pWorkerThreadCount;
65 m_workerThreads = new Thread[m_WorkerThreadCount]; 79 m_workerThreads = new Thread[m_WorkerThreadCount];
66 } 80 }
67 81
68 public void Start() 82 public void Start()
69 { 83 {
70 //startup worker threads 84 IsRunning = true;
71 for (uint i = 0; i < m_WorkerThreadCount; i++) 85
86 if (PerformResponsesAsync)
72 { 87 {
73 m_workerThreads[i] 88 //startup worker threads
74 = Watchdog.StartThread( 89 for (uint i = 0; i < m_WorkerThreadCount; i++)
75 PoolWorkerJob, 90 {
76 string.Format("PollServiceWorkerThread{0}:{1}", i, m_server.Port), 91 m_workerThreads[i]
77 ThreadPriority.Normal, 92 = Watchdog.StartThread(
78 false, 93 PoolWorkerJob,
79 false, 94 string.Format("PollServiceWorkerThread{0}:{1}", i, m_server.Port),
80 null, 95 ThreadPriority.Normal,
81 int.MaxValue); 96 false,
82 } 97 false,
98 null,
99 int.MaxValue);
100 }
83 101
84 Watchdog.StartThread( 102 Watchdog.StartThread(
85 this.CheckLongPollThreads, 103 this.CheckLongPollThreads,
86 string.Format("LongPollServiceWatcherThread:{0}", m_server.Port), 104 string.Format("LongPollServiceWatcherThread:{0}", m_server.Port),
87 ThreadPriority.Normal, 105 ThreadPriority.Normal,
88 false, 106 false,
89 true, 107 true,
90 null, 108 null,
91 1000 * 60 * 10); 109 1000 * 60 * 10);
110 }
92 } 111 }
93 112
94 private void ReQueueEvent(PollServiceHttpRequest req) 113 private void ReQueueEvent(PollServiceHttpRequest req)
95 { 114 {
96 if (m_running) 115 if (IsRunning)
97 { 116 {
98 // delay the enqueueing for 100ms. There's no need to have the event 117 // delay the enqueueing for 100ms. There's no need to have the event
99 // actively on the queue 118 // actively on the queue
@@ -109,7 +128,7 @@ namespace OpenSim.Framework.Servers.HttpServer
109 128
110 public void Enqueue(PollServiceHttpRequest req) 129 public void Enqueue(PollServiceHttpRequest req)
111 { 130 {
112 if (m_running) 131 if (IsRunning)
113 { 132 {
114 if (req.PollServiceArgs.Type == PollServiceEventArgs.EventType.LongPoll) 133 if (req.PollServiceArgs.Type == PollServiceEventArgs.EventType.LongPoll)
115 { 134 {
@@ -129,7 +148,7 @@ namespace OpenSim.Framework.Servers.HttpServer
129 // All other types of tasks (Inventory handlers, http-in, etc) don't have the long-poll nature, 148 // All other types of tasks (Inventory handlers, http-in, etc) don't have the long-poll nature,
130 // so if they aren't ready to be served by a worker thread (no events), they are placed 149 // so if they aren't ready to be served by a worker thread (no events), they are placed
131 // directly back in the "ready-to-serve" queue by the worker thread. 150 // directly back in the "ready-to-serve" queue by the worker thread.
132 while (m_running) 151 while (IsRunning)
133 { 152 {
134 Thread.Sleep(500); 153 Thread.Sleep(500);
135 Watchdog.UpdateThread(); 154 Watchdog.UpdateThread();
@@ -137,7 +156,7 @@ namespace OpenSim.Framework.Servers.HttpServer
137// List<PollServiceHttpRequest> not_ready = new List<PollServiceHttpRequest>(); 156// List<PollServiceHttpRequest> not_ready = new List<PollServiceHttpRequest>();
138 lock (m_longPollRequests) 157 lock (m_longPollRequests)
139 { 158 {
140 if (m_longPollRequests.Count > 0 && m_running) 159 if (m_longPollRequests.Count > 0 && IsRunning)
141 { 160 {
142 List<PollServiceHttpRequest> ready = m_longPollRequests.FindAll(req => 161 List<PollServiceHttpRequest> ready = m_longPollRequests.FindAll(req =>
143 (req.PollServiceArgs.HasEvents(req.RequestID, req.PollServiceArgs.Id) || // there are events in this EQ 162 (req.PollServiceArgs.HasEvents(req.RequestID, req.PollServiceArgs.Id) || // there are events in this EQ
@@ -158,7 +177,7 @@ namespace OpenSim.Framework.Servers.HttpServer
158 177
159 public void Stop() 178 public void Stop()
160 { 179 {
161 m_running = false; 180 IsRunning = false;
162// m_timeout = -10000; // cause all to expire 181// m_timeout = -10000; // cause all to expire
163 Thread.Sleep(1000); // let the world move 182 Thread.Sleep(1000); // let the world move
164 183
@@ -169,7 +188,7 @@ namespace OpenSim.Framework.Servers.HttpServer
169 188
170 lock (m_longPollRequests) 189 lock (m_longPollRequests)
171 { 190 {
172 if (m_longPollRequests.Count > 0 && m_running) 191 if (m_longPollRequests.Count > 0 && IsRunning)
173 m_longPollRequests.ForEach(req => m_requests.Enqueue(req)); 192 m_longPollRequests.ForEach(req => m_requests.Enqueue(req));
174 } 193 }
175 194
@@ -194,68 +213,82 @@ namespace OpenSim.Framework.Servers.HttpServer
194 213
195 private void PoolWorkerJob() 214 private void PoolWorkerJob()
196 { 215 {
197 while (m_running) 216 while (IsRunning)
198 { 217 {
199 PollServiceHttpRequest req = m_requests.Dequeue(5000);
200 //m_log.WarnFormat("[YYY]: Dequeued {0}", (req == null ? "null" : req.PollServiceArgs.Type.ToString()));
201
202 Watchdog.UpdateThread(); 218 Watchdog.UpdateThread();
203 if (req != null) 219 WaitPerformResponse();
220 }
221 }
222
223 public void WaitPerformResponse()
224 {
225 PollServiceHttpRequest req = m_requests.Dequeue(5000);
226// m_log.DebugFormat("[YYY]: Dequeued {0}", (req == null ? "null" : req.PollServiceArgs.Type.ToString()));
227
228 if (req != null)
229 {
230 try
204 { 231 {
205 try 232 if (req.PollServiceArgs.HasEvents(req.RequestID, req.PollServiceArgs.Id))
206 { 233 {
207 if (req.PollServiceArgs.HasEvents(req.RequestID, req.PollServiceArgs.Id)) 234 Hashtable responsedata = req.PollServiceArgs.GetEvents(req.RequestID, req.PollServiceArgs.Id);
208 {
209 Hashtable responsedata = req.PollServiceArgs.GetEvents(req.RequestID, req.PollServiceArgs.Id);
210 235
211 if (responsedata == null) 236 if (responsedata == null)
212 continue; 237 return;
213 238
214 if (req.PollServiceArgs.Type == PollServiceEventArgs.EventType.LongPoll) // This is the event queue 239 // This is the event queue.
240 // Even if we're not running we can still perform responses by explicit request.
241 if (req.PollServiceArgs.Type == PollServiceEventArgs.EventType.LongPoll
242 || !PerformResponsesAsync)
243 {
244 try
245 {
246 req.DoHTTPGruntWork(m_server, responsedata);
247 }
248 catch (ObjectDisposedException e) // Browser aborted before we could read body, server closed the stream
249 {
250 // Ignore it, no need to reply
251 m_log.Error(e);
252 }
253 }
254 else
255 {
256 m_threadPool.QueueWorkItem(x =>
215 { 257 {
216 try 258 try
217 { 259 {
218 req.DoHTTPGruntWork(m_server, responsedata); 260 req.DoHTTPGruntWork(m_server, responsedata);
219 } 261 }
220 catch (ObjectDisposedException) // Browser aborted before we could read body, server closed the stream 262 catch (ObjectDisposedException e) // Browser aborted before we could read body, server closed the stream
221 { 263 {
222 // Ignore it, no need to reply 264 // Ignore it, no need to reply
265 m_log.Error(e);
223 } 266 }
224 } 267 catch (Exception e)
225 else
226 {
227 m_threadPool.QueueWorkItem(x =>
228 { 268 {
229 try 269 m_log.Error(e);
230 { 270 }
231 req.DoHTTPGruntWork(m_server, responsedata); 271
232 } 272 return null;
233 catch (ObjectDisposedException) // Browser aborted before we could read body, server closed the stream 273 }, null);
234 { 274 }
235 // Ignore it, no need to reply 275 }
236 } 276 else
237 277 {
238 return null; 278 if ((Environment.TickCount - req.RequestTime) > req.PollServiceArgs.TimeOutms)
239 }, null); 279 {
240 } 280 req.DoHTTPGruntWork(
281 m_server, req.PollServiceArgs.NoEvents(req.RequestID, req.PollServiceArgs.Id));
241 } 282 }
242 else 283 else
243 { 284 {
244 if ((Environment.TickCount - req.RequestTime) > req.PollServiceArgs.TimeOutms) 285 ReQueueEvent(req);
245 {
246 req.DoHTTPGruntWork(
247 m_server, req.PollServiceArgs.NoEvents(req.RequestID, req.PollServiceArgs.Id));
248 }
249 else
250 {
251 ReQueueEvent(req);
252 }
253 } 286 }
254 } 287 }
255 catch (Exception e) 288 }
256 { 289 catch (Exception e)
257 m_log.ErrorFormat("Exception in poll service thread: " + e.ToString()); 290 {
258 } 291 m_log.ErrorFormat("Exception in poll service thread: " + e.ToString());
259 } 292 }
260 } 293 }
261 } 294 }
diff --git a/OpenSim/Framework/Servers/Tests/OSHttpTests.cs b/OpenSim/Framework/Servers/Tests/OSHttpTests.cs
index 5b912b4..5c0e0df 100644
--- a/OpenSim/Framework/Servers/Tests/OSHttpTests.cs
+++ b/OpenSim/Framework/Servers/Tests/OSHttpTests.cs
@@ -41,323 +41,7 @@ namespace OpenSim.Framework.Servers.Tests
41{ 41{
42 [TestFixture] 42 [TestFixture]
43 public class OSHttpTests : OpenSimTestCase 43 public class OSHttpTests : OpenSimTestCase
44 { 44 {
45 // we need an IHttpClientContext for our tests
46 public class TestHttpClientContext: IHttpClientContext
47 {
48 private bool _secured;
49 public bool IsSecured
50 {
51 get { return _secured; }
52 }
53 public bool Secured
54 {
55 get { return _secured; }
56 }
57
58 public TestHttpClientContext(bool secured)
59 {
60 _secured = secured;
61 }
62
63 public void Disconnect(SocketError error) {}
64 public void Respond(string httpVersion, HttpStatusCode statusCode, string reason, string body) {}
65 public void Respond(string httpVersion, HttpStatusCode statusCode, string reason) {}
66 public void Respond(string body) {}
67 public void Send(byte[] buffer) {}
68 public void Send(byte[] buffer, int offset, int size) {}
69 public void Respond(string httpVersion, HttpStatusCode statusCode, string reason, string body, string contentType) {}
70 public void Close() { }
71 public bool EndWhenDone { get { return false;} set { return;}}
72
73 public HTTPNetworkContext GiveMeTheNetworkStreamIKnowWhatImDoing()
74 {
75 return new HTTPNetworkContext();
76 }
77
78 public event EventHandler<DisconnectedEventArgs> Disconnected = delegate { };
79 /// <summary>
80 /// A request have been received in the context.
81 /// </summary>
82 public event EventHandler<RequestEventArgs> RequestReceived = delegate { };
83
84 }
85
86 public class TestHttpRequest: IHttpRequest
87 {
88 private string _uriPath;
89 public bool BodyIsComplete
90 {
91 get { return true; }
92 }
93 public string[] AcceptTypes
94 {
95 get {return _acceptTypes; }
96 }
97 private string[] _acceptTypes;
98 public Stream Body
99 {
100 get { return _body; }
101 set { _body = value;}
102 }
103 private Stream _body;
104 public ConnectionType Connection
105 {
106 get { return _connection; }
107 set { _connection = value; }
108 }
109 private ConnectionType _connection;
110 public int ContentLength
111 {
112 get { return _contentLength; }
113 set { _contentLength = value; }
114 }
115 private int _contentLength;
116 public NameValueCollection Headers
117 {
118 get { return _headers; }
119 }
120 private NameValueCollection _headers = new NameValueCollection();
121 public string HttpVersion
122 {
123 get { return _httpVersion; }
124 set { _httpVersion = value; }
125 }
126 private string _httpVersion = null;
127 public string Method
128 {
129 get { return _method; }
130 set { _method = value; }
131 }
132 private string _method = null;
133 public HttpInput QueryString
134 {
135 get { return _queryString; }
136 }
137 private HttpInput _queryString = null;
138 public Uri Uri
139 {
140 get { return _uri; }
141 set { _uri = value; }
142 }
143 private Uri _uri = null;
144 public string[] UriParts
145 {
146 get { return _uri.Segments; }
147 }
148 public HttpParam Param
149 {
150 get { return null; }
151 }
152 public HttpForm Form
153 {
154 get { return null; }
155 }
156 public bool IsAjax
157 {
158 get { return false; }
159 }
160 public RequestCookies Cookies
161 {
162 get { return null; }
163 }
164
165 public TestHttpRequest() {}
166
167 public TestHttpRequest(string contentEncoding, string contentType, string userAgent,
168 string remoteAddr, string remotePort, string[] acceptTypes,
169 ConnectionType connectionType, int contentLength, Uri uri)
170 {
171 _headers["content-encoding"] = contentEncoding;
172 _headers["content-type"] = contentType;
173 _headers["user-agent"] = userAgent;
174 _headers["remote_addr"] = remoteAddr;
175 _headers["remote_port"] = remotePort;
176
177 _acceptTypes = acceptTypes;
178 _connection = connectionType;
179 _contentLength = contentLength;
180 _uri = uri;
181 }
182
183 public void DecodeBody(FormDecoderProvider providers) {}
184 public void SetCookies(RequestCookies cookies) {}
185 public void AddHeader(string name, string value)
186 {
187 _headers.Add(name, value);
188 }
189 public int AddToBody(byte[] bytes, int offset, int length)
190 {
191 return 0;
192 }
193 public void Clear() {}
194
195 public object Clone()
196 {
197 TestHttpRequest clone = new TestHttpRequest();
198 clone._acceptTypes = _acceptTypes;
199 clone._connection = _connection;
200 clone._contentLength = _contentLength;
201 clone._uri = _uri;
202 clone._headers = new NameValueCollection(_headers);
203
204 return clone;
205 }
206 public IHttpResponse CreateResponse(IHttpClientContext context)
207 {
208 return new HttpResponse(context, this);
209 }
210 /// <summary>
211 /// Path and query (will be merged with the host header) and put in Uri
212 /// </summary>
213 /// <see cref="Uri"/>
214 public string UriPath
215 {
216 get { return _uriPath; }
217 set
218 {
219 _uriPath = value;
220
221 }
222 }
223
224 }
225
226 public class TestHttpResponse: IHttpResponse
227 {
228 public Stream Body
229 {
230 get { return _body; }
231
232 set { _body = value; }
233 }
234 private Stream _body;
235
236 public string ProtocolVersion
237 {
238 get { return _protocolVersion; }
239 set { _protocolVersion = value; }
240 }
241 private string _protocolVersion;
242
243 public bool Chunked
244 {
245 get { return _chunked; }
246
247 set { _chunked = value; }
248 }
249 private bool _chunked;
250
251 public ConnectionType Connection
252 {
253 get { return _connection; }
254
255 set { _connection = value; }
256 }
257 private ConnectionType _connection;
258
259 public Encoding Encoding
260 {
261 get { return _encoding; }
262
263 set { _encoding = value; }
264 }
265 private Encoding _encoding;
266
267 public int KeepAlive
268 {
269 get { return _keepAlive; }
270
271 set { _keepAlive = value; }
272 }
273 private int _keepAlive;
274
275 public HttpStatusCode Status
276 {
277 get { return _status; }
278
279 set { _status = value; }
280 }
281 private HttpStatusCode _status;
282
283 public string Reason
284 {
285 get { return _reason; }
286
287 set { _reason = value; }
288 }
289 private string _reason;
290
291 public long ContentLength
292 {
293 get { return _contentLength; }
294
295 set { _contentLength = value; }
296 }
297 private long _contentLength;
298
299 public string ContentType
300 {
301 get { return _contentType; }
302
303 set { _contentType = value; }
304 }
305 private string _contentType;
306
307 public bool HeadersSent
308 {
309 get { return _headersSent; }
310 }
311 private bool _headersSent;
312
313 public bool Sent
314 {
315 get { return _sent; }
316 }
317 private bool _sent;
318
319 public ResponseCookies Cookies
320 {
321 get { return _cookies; }
322 }
323 private ResponseCookies _cookies = null;
324
325 public TestHttpResponse()
326 {
327 _headersSent = false;
328 _sent = false;
329 }
330
331 public void AddHeader(string name, string value) {}
332 public void Send()
333 {
334 if (!_headersSent) SendHeaders();
335 if (_sent) throw new InvalidOperationException("stuff already sent");
336 _sent = true;
337 }
338
339 public void SendBody(byte[] buffer, int offset, int count)
340 {
341 if (!_headersSent) SendHeaders();
342 _sent = true;
343 }
344 public void SendBody(byte[] buffer)
345 {
346 if (!_headersSent) SendHeaders();
347 _sent = true;
348 }
349
350 public void SendHeaders()
351 {
352 if (_headersSent) throw new InvalidOperationException("headers already sent");
353 _headersSent = true;
354 }
355
356 public void Redirect(Uri uri) {}
357 public void Redirect(string url) {}
358 }
359
360
361 public OSHttpRequest req0; 45 public OSHttpRequest req0;
362 public OSHttpRequest req1; 46 public OSHttpRequest req1;
363 47
@@ -429,4 +113,4 @@ namespace OpenSim.Framework.Servers.Tests
429 Assert.That(rsp0.ContentType, Is.EqualTo("text/xml")); 113 Assert.That(rsp0.ContentType, Is.EqualTo("text/xml"));
430 } 114 }
431 } 115 }
432} 116} \ No newline at end of file
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/Tests/WebFetchInvDescModuleTests.cs b/OpenSim/Region/ClientStack/Linden/Caps/Tests/WebFetchInvDescModuleTests.cs
new file mode 100644
index 0000000..edc5016
--- /dev/null
+++ b/OpenSim/Region/ClientStack/Linden/Caps/Tests/WebFetchInvDescModuleTests.cs
@@ -0,0 +1,158 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections;
30using System.Collections.Generic;
31using System.IO;
32using System.Net;
33using System.Text;
34using HttpServer;
35using log4net.Config;
36using Nini.Config;
37using NUnit.Framework;
38using OpenMetaverse;
39using OpenMetaverse.Packets;
40using OpenMetaverse.StructuredData;
41using OpenSim.Framework;
42using OpenSim.Framework.Capabilities;
43using OpenSim.Framework.Servers;
44using OpenSim.Framework.Servers.HttpServer;
45using OpenSim.Region.ClientStack.Linden;
46using OpenSim.Region.CoreModules.Framework;
47using OpenSim.Region.Framework.Scenes;
48using OpenSim.Services.Interfaces;
49using OpenSim.Tests.Common;
50using OpenSim.Tests.Common.Mock;
51using OSDArray = OpenMetaverse.StructuredData.OSDArray;
52using OSDMap = OpenMetaverse.StructuredData.OSDMap;
53
54namespace OpenSim.Region.ClientStack.Linden.Caps.Tests
55{
56 [TestFixture]
57 public class WebFetchInvDescModuleTests : OpenSimTestCase
58 {
59 [TestFixtureSetUp]
60 public void TestFixtureSetUp()
61 {
62 // Don't allow tests to be bamboozled by asynchronous events. Execute everything on the same thread.
63 Util.FireAndForgetMethod = FireAndForgetMethod.RegressionTest;
64 }
65
66 [TestFixtureTearDown]
67 public void TestFixureTearDown()
68 {
69 // We must set this back afterwards, otherwise later tests will fail since they're expecting multiple
70 // threads. Possibly, later tests should be rewritten so none of them require async stuff (which regression
71 // tests really shouldn't).
72 Util.FireAndForgetMethod = Util.DefaultFireAndForgetMethod;
73 }
74
75 [SetUp]
76 public override void SetUp()
77 {
78 base.SetUp();
79
80 // This is an unfortunate bit of clean up we have to do because MainServer manages things through static
81 // variables and the VM is not restarted between tests.
82 uint port = 9999;
83 MainServer.RemoveHttpServer(port);
84
85 BaseHttpServer server = new BaseHttpServer(port, false, 0, "");
86 MainServer.AddHttpServer(server);
87 MainServer.Instance = server;
88
89 server.Start(false);
90 }
91
92 [Test]
93 public void TestInventoryDescendentsFetch()
94 {
95 TestHelpers.InMethod();
96 TestHelpers.EnableLogging();
97
98 BaseHttpServer httpServer = MainServer.Instance;
99 Scene scene = new SceneHelpers().SetupScene();
100
101 CapabilitiesModule capsModule = new CapabilitiesModule();
102 WebFetchInvDescModule wfidModule = new WebFetchInvDescModule(false);
103
104 IConfigSource config = new IniConfigSource();
105 config.AddConfig("ClientStack.LindenCaps");
106 config.Configs["ClientStack.LindenCaps"].Set("Cap_FetchInventoryDescendents2", "localhost");
107
108 SceneHelpers.SetupSceneModules(scene, config, capsModule, wfidModule);
109
110 UserAccount ua = UserAccountHelpers.CreateUserWithInventory(scene, TestHelpers.ParseTail(0x1));
111
112 // We need a user present to have any capabilities set up
113 SceneHelpers.AddScenePresence(scene, ua.PrincipalID);
114
115 TestHttpRequest req = new TestHttpRequest();
116 OpenSim.Framework.Capabilities.Caps userCaps = capsModule.GetCapsForUser(ua.PrincipalID);
117 PollServiceEventArgs pseArgs;
118 userCaps.TryGetPollHandler("FetchInventoryDescendents2", out pseArgs);
119 req.UriPath = pseArgs.Url;
120 req.Uri = new Uri(req.UriPath);
121
122 // Retrieve root folder details directly so that we can request
123 InventoryFolderBase folder = scene.InventoryService.GetRootFolder(ua.PrincipalID);
124
125 OSDMap osdFolder = new OSDMap();
126 osdFolder["folder_id"] = folder.ID;
127 osdFolder["owner_id"] = ua.PrincipalID;
128 osdFolder["fetch_folders"] = true;
129 osdFolder["fetch_items"] = true;
130 osdFolder["sort_order"] = 0;
131
132 OSDArray osdFoldersArray = new OSDArray();
133 osdFoldersArray.Add(osdFolder);
134
135 OSDMap osdReqMap = new OSDMap();
136 osdReqMap["folders"] = osdFoldersArray;
137
138 req.Body = new MemoryStream(OSDParser.SerializeLLSDXmlBytes(osdReqMap));
139
140 TestHttpClientContext context = new TestHttpClientContext(false);
141 MainServer.Instance.OnRequest(context, new RequestEventArgs(req));
142
143 // Drive processing of the queued inventory request synchronously.
144 wfidModule.WaitProcessQueuedInventoryRequest();
145 MainServer.Instance.PollServiceRequestManager.WaitPerformResponse();
146
147// System.Threading.Thread.Sleep(10000);
148
149 OSDMap responseOsd = (OSDMap)OSDParser.DeserializeLLSDXml(context.ResponseBody);
150 OSDArray foldersOsd = (OSDArray)responseOsd["folders"];
151 OSDMap folderOsd = (OSDMap)foldersOsd[0];
152
153 // A sanity check that the response has the expected number of descendents for a default inventory
154 // TODO: Need a more thorough check.
155 Assert.That((int)folderOsd["descendents"], Is.EqualTo(14));
156 }
157 }
158} \ No newline at end of file
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/WebFetchInvDescModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/WebFetchInvDescModule.cs
index 340d2e7..f0dccda 100644
--- a/OpenSim/Region/ClientStack/Linden/Caps/WebFetchInvDescModule.cs
+++ b/OpenSim/Region/ClientStack/Linden/Caps/WebFetchInvDescModule.cs
@@ -65,6 +65,15 @@ namespace OpenSim.Region.ClientStack.Linden
65 65
66 // private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 66 // private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
67 67
68
69 /// <summary>
70 /// Control whether requests will be processed asynchronously.
71 /// </summary>
72 /// <remarks>
73 /// Defaults to true. Can currently not be changed once a region has been added to the module.
74 /// </remarks>
75 public bool ProcessQueuedRequestsAsync { get; private set; }
76
68 private Scene m_scene; 77 private Scene m_scene;
69 78
70 private IInventoryService m_InventoryService; 79 private IInventoryService m_InventoryService;
@@ -84,6 +93,13 @@ namespace OpenSim.Region.ClientStack.Linden
84 93
85 #region ISharedRegionModule Members 94 #region ISharedRegionModule Members
86 95
96 public WebFetchInvDescModule() : this(true) {}
97
98 public WebFetchInvDescModule(bool processQueuedResultsAsync)
99 {
100 ProcessQueuedRequestsAsync = processQueuedResultsAsync;
101 }
102
87 public void Initialise(IConfigSource source) 103 public void Initialise(IConfigSource source)
88 { 104 {
89 IConfig config = source.Configs["ClientStack.LindenCaps"]; 105 IConfig config = source.Configs["ClientStack.LindenCaps"];
@@ -114,8 +130,16 @@ namespace OpenSim.Region.ClientStack.Linden
114 130
115 m_scene.EventManager.OnRegisterCaps -= RegisterCaps; 131 m_scene.EventManager.OnRegisterCaps -= RegisterCaps;
116 132
117 foreach (Thread t in m_workerThreads) 133 if (ProcessQueuedRequestsAsync)
118 Watchdog.AbortThread(t.ManagedThreadId); 134 {
135 if (m_workerThreads != null)
136 {
137 foreach (Thread t in m_workerThreads)
138 Watchdog.AbortThread(t.ManagedThreadId);
139
140 m_workerThreads = null;
141 }
142 }
119 143
120 m_scene = null; 144 m_scene = null;
121 } 145 }
@@ -133,7 +157,7 @@ namespace OpenSim.Region.ClientStack.Linden
133 157
134 m_scene.EventManager.OnRegisterCaps += RegisterCaps; 158 m_scene.EventManager.OnRegisterCaps += RegisterCaps;
135 159
136 if (m_workerThreads == null) 160 if (ProcessQueuedRequestsAsync && m_workerThreads == null)
137 { 161 {
138 m_workerThreads = new Thread[2]; 162 m_workerThreads = new Thread[2];
139 163
@@ -358,11 +382,16 @@ namespace OpenSim.Region.ClientStack.Linden
358 { 382 {
359 Watchdog.UpdateThread(); 383 Watchdog.UpdateThread();
360 384
361 aPollRequest poolreq = m_queue.Dequeue(); 385 WaitProcessQueuedInventoryRequest();
362
363 if (poolreq != null && poolreq.thepoll != null)
364 poolreq.thepoll.Process(poolreq);
365 } 386 }
366 } 387 }
388
389 public void WaitProcessQueuedInventoryRequest()
390 {
391 aPollRequest poolreq = m_queue.Dequeue();
392
393 if (poolreq != null && poolreq.thepoll != null)
394 poolreq.thepoll.Process(poolreq);
395 }
367 } 396 }
368} 397}
diff --git a/OpenSim/Region/CoreModules/Framework/Caps/CapabilitiesModule.cs b/OpenSim/Region/CoreModules/Framework/Caps/CapabilitiesModule.cs
index 13cc99a..817ef85 100644
--- a/OpenSim/Region/CoreModules/Framework/Caps/CapabilitiesModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/Caps/CapabilitiesModule.cs
@@ -137,6 +137,10 @@ namespace OpenSim.Region.CoreModules.Framework
137 // agentId, m_scene.RegionInfo.RegionName, oldCaps.CapsObjectPath, capsObjectPath); 137 // agentId, m_scene.RegionInfo.RegionName, oldCaps.CapsObjectPath, capsObjectPath);
138 } 138 }
139 139
140// m_log.DebugFormat(
141// "[CAPS]: Adding capabilities for agent {0} in {1} with path {2}",
142// agentId, m_scene.RegionInfo.RegionName, capsObjectPath);
143
140 caps = new Caps(MainServer.Instance, m_scene.RegionInfo.ExternalHostName, 144 caps = new Caps(MainServer.Instance, m_scene.RegionInfo.ExternalHostName,
141 (MainServer.Instance == null) ? 0: MainServer.Instance.Port, 145 (MainServer.Instance == null) ? 0: MainServer.Instance.Port,
142 capsObjectPath, agentId, m_scene.RegionInfo.RegionName); 146 capsObjectPath, agentId, m_scene.RegionInfo.RegionName);
diff --git a/OpenSim/Tests/Common/Mock/TestHttpClientContext.cs b/OpenSim/Tests/Common/Mock/TestHttpClientContext.cs
new file mode 100644
index 0000000..5a55b09
--- /dev/null
+++ b/OpenSim/Tests/Common/Mock/TestHttpClientContext.cs
@@ -0,0 +1,110 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections.Generic;
30using System.IO;
31using System.Net;
32using System.Net.Sockets;
33using System.Text;
34using HttpServer;
35using OpenSim.Framework;
36
37namespace OpenSim.Tests.Common
38{
39 public class TestHttpClientContext: IHttpClientContext
40 {
41 /// <summary>
42 /// Bodies of responses from the server.
43 /// </summary>
44 public string ResponseBody
45 {
46 get { return Encoding.UTF8.GetString(m_responseStream.ToArray()); }
47 }
48
49 public Byte[] ResponseBodyBytes
50 {
51 get{ return m_responseStream.ToArray(); }
52 }
53
54 private MemoryStream m_responseStream = new MemoryStream();
55
56 public bool IsSecured { get; set; }
57
58 public bool Secured
59 {
60 get { return IsSecured; }
61 set { IsSecured = value; }
62 }
63
64 public TestHttpClientContext(bool secured)
65 {
66 Secured = secured;
67 }
68
69 public void Disconnect(SocketError error)
70 {
71// Console.WriteLine("TestHttpClientContext.Disconnect Received disconnect with status {0}", error);
72 }
73
74 public void Respond(string httpVersion, HttpStatusCode statusCode, string reason, string body) {Console.WriteLine("x");}
75 public void Respond(string httpVersion, HttpStatusCode statusCode, string reason) {Console.WriteLine("xx");}
76 public void Respond(string body) { Console.WriteLine("xxx");}
77
78 public void Send(byte[] buffer)
79 {
80 // Getting header data here
81// Console.WriteLine("xxxx: Got {0}", Encoding.UTF8.GetString(buffer));
82 }
83
84 public void Send(byte[] buffer, int offset, int size)
85 {
86// Util.PrintCallStack();
87//
88// Console.WriteLine(
89// "TestHttpClientContext.Send(byte[], int, int) got offset={0}, size={1}, buffer={2}",
90// offset, size, Encoding.UTF8.GetString(buffer));
91
92 m_responseStream.Write(buffer, offset, size);
93 }
94
95 public void Respond(string httpVersion, HttpStatusCode statusCode, string reason, string body, string contentType) {Console.WriteLine("xxxxxx");}
96 public void Close() { }
97 public bool EndWhenDone { get { return false;} set { return;}}
98
99 public HTTPNetworkContext GiveMeTheNetworkStreamIKnowWhatImDoing()
100 {
101 return new HTTPNetworkContext();
102 }
103
104 public event EventHandler<DisconnectedEventArgs> Disconnected = delegate { };
105 /// <summary>
106 /// A request have been received in the context.
107 /// </summary>
108 public event EventHandler<RequestEventArgs> RequestReceived = delegate { };
109 }
110} \ No newline at end of file
diff --git a/OpenSim/Tests/Common/Mock/TestHttpRequest.cs b/OpenSim/Tests/Common/Mock/TestHttpRequest.cs
new file mode 100644
index 0000000..b868895
--- /dev/null
+++ b/OpenSim/Tests/Common/Mock/TestHttpRequest.cs
@@ -0,0 +1,174 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections.Specialized;
30using System.IO;
31using HttpServer;
32using HttpServer.FormDecoders;
33
34namespace OpenSim.Tests.Common
35{
36 public class TestHttpRequest: IHttpRequest
37 {
38 private string _uriPath;
39 public bool BodyIsComplete
40 {
41 get { return true; }
42 }
43 public string[] AcceptTypes
44 {
45 get {return _acceptTypes; }
46 }
47 private string[] _acceptTypes;
48 public Stream Body
49 {
50 get { return _body; }
51 set { _body = value;}
52 }
53 private Stream _body;
54 public ConnectionType Connection
55 {
56 get { return _connection; }
57 set { _connection = value; }
58 }
59 private ConnectionType _connection;
60 public int ContentLength
61 {
62 get { return _contentLength; }
63 set { _contentLength = value; }
64 }
65 private int _contentLength;
66 public NameValueCollection Headers
67 {
68 get { return _headers; }
69 }
70 private NameValueCollection _headers = new NameValueCollection();
71
72 public string HttpVersion { get; set; }
73
74 public string Method
75 {
76 get { return _method; }
77 set { _method = value; }
78 }
79 private string _method = null;
80 public HttpInput QueryString
81 {
82 get { return _queryString; }
83 }
84 private HttpInput _queryString = null;
85 public Uri Uri
86 {
87 get { return _uri; }
88 set { _uri = value; }
89 }
90 private Uri _uri = null;
91 public string[] UriParts
92 {
93 get { return _uri.Segments; }
94 }
95 public HttpParam Param
96 {
97 get { return null; }
98 }
99 public HttpForm Form
100 {
101 get { return null; }
102 }
103 public bool IsAjax
104 {
105 get { return false; }
106 }
107 public RequestCookies Cookies
108 {
109 get { return null; }
110 }
111
112 public TestHttpRequest()
113 {
114 HttpVersion = "HTTP/1.1";
115 }
116
117 public TestHttpRequest(string contentEncoding, string contentType, string userAgent,
118 string remoteAddr, string remotePort, string[] acceptTypes,
119 ConnectionType connectionType, int contentLength, Uri uri) : base()
120 {
121 _headers["content-encoding"] = contentEncoding;
122 _headers["content-type"] = contentType;
123 _headers["user-agent"] = userAgent;
124 _headers["remote_addr"] = remoteAddr;
125 _headers["remote_port"] = remotePort;
126
127 _acceptTypes = acceptTypes;
128 _connection = connectionType;
129 _contentLength = contentLength;
130 _uri = uri;
131 }
132
133 public void DecodeBody(FormDecoderProvider providers) {}
134 public void SetCookies(RequestCookies cookies) {}
135 public void AddHeader(string name, string value)
136 {
137 _headers.Add(name, value);
138 }
139 public int AddToBody(byte[] bytes, int offset, int length)
140 {
141 return 0;
142 }
143 public void Clear() {}
144
145 public object Clone()
146 {
147 TestHttpRequest clone = new TestHttpRequest();
148 clone._acceptTypes = _acceptTypes;
149 clone._connection = _connection;
150 clone._contentLength = _contentLength;
151 clone._uri = _uri;
152 clone._headers = new NameValueCollection(_headers);
153
154 return clone;
155 }
156 public IHttpResponse CreateResponse(IHttpClientContext context)
157 {
158 return new HttpResponse(context, this);
159 }
160 /// <summary>
161 /// Path and query (will be merged with the host header) and put in Uri
162 /// </summary>
163 /// <see cref="Uri"/>
164 public string UriPath
165 {
166 get { return _uriPath; }
167 set
168 {
169 _uriPath = value;
170
171 }
172 }
173 }
174} \ No newline at end of file
diff --git a/OpenSim/Tests/Common/Mock/TestHttpResponse.cs b/OpenSim/Tests/Common/Mock/TestHttpResponse.cs
new file mode 100644
index 0000000..ff47c10
--- /dev/null
+++ b/OpenSim/Tests/Common/Mock/TestHttpResponse.cs
@@ -0,0 +1,171 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.IO;
30using System.Net;
31using System.Text;
32using HttpServer;
33
34namespace OpenSim.Tests.Common
35{
36 public class TestHttpResponse: IHttpResponse
37 {
38 public Stream Body
39 {
40 get { return _body; }
41
42 set { _body = value; }
43 }
44 private Stream _body;
45
46 public string ProtocolVersion
47 {
48 get { return _protocolVersion; }
49 set { _protocolVersion = value; }
50 }
51 private string _protocolVersion;
52
53 public bool Chunked
54 {
55 get { return _chunked; }
56
57 set { _chunked = value; }
58 }
59 private bool _chunked;
60
61 public ConnectionType Connection
62 {
63 get { return _connection; }
64
65 set { _connection = value; }
66 }
67 private ConnectionType _connection;
68
69 public Encoding Encoding
70 {
71 get { return _encoding; }
72
73 set { _encoding = value; }
74 }
75 private Encoding _encoding;
76
77 public int KeepAlive
78 {
79 get { return _keepAlive; }
80
81 set { _keepAlive = value; }
82 }
83 private int _keepAlive;
84
85 public HttpStatusCode Status
86 {
87 get { return _status; }
88
89 set { _status = value; }
90 }
91 private HttpStatusCode _status;
92
93 public string Reason
94 {
95 get { return _reason; }
96
97 set { _reason = value; }
98 }
99 private string _reason;
100
101 public long ContentLength
102 {
103 get { return _contentLength; }
104
105 set { _contentLength = value; }
106 }
107 private long _contentLength;
108
109 public string ContentType
110 {
111 get { return _contentType; }
112
113 set { _contentType = value; }
114 }
115 private string _contentType;
116
117 public bool HeadersSent
118 {
119 get { return _headersSent; }
120 }
121 private bool _headersSent;
122
123 public bool Sent
124 {
125 get { return _sent; }
126 }
127 private bool _sent;
128
129 public ResponseCookies Cookies
130 {
131 get { return _cookies; }
132 }
133 private ResponseCookies _cookies = null;
134
135 public TestHttpResponse()
136 {
137 _headersSent = false;
138 _sent = false;
139 }
140
141 public void AddHeader(string name, string value) {}
142
143 public void Send()
144 {
145 if (!_headersSent) SendHeaders();
146 if (_sent) throw new InvalidOperationException("stuff already sent");
147 _sent = true;
148 }
149
150 public void SendBody(byte[] buffer, int offset, int count)
151 {
152 if (!_headersSent) SendHeaders();
153 _sent = true;
154 }
155
156 public void SendBody(byte[] buffer)
157 {
158 if (!_headersSent) SendHeaders();
159 _sent = true;
160 }
161
162 public void SendHeaders()
163 {
164 if (_headersSent) throw new InvalidOperationException("headers already sent");
165 _headersSent = true;
166 }
167
168 public void Redirect(Uri uri) {}
169 public void Redirect(string url) {}
170 }
171} \ No newline at end of file
diff --git a/prebuild.xml b/prebuild.xml
index 356110a..c16d6e6 100644
--- a/prebuild.xml
+++ b/prebuild.xml
@@ -3321,12 +3321,14 @@
3321 <ReferencePath>../../../../../bin/</ReferencePath> 3321 <ReferencePath>../../../../../bin/</ReferencePath>
3322 <Reference name="System"/> 3322 <Reference name="System"/>
3323 <Reference name="System.Xml"/> 3323 <Reference name="System.Xml"/>
3324 <Reference name="HttpServer_OpenSim" path="../../../../../bin/"/>
3324 <Reference name="log4net" path="../../../../../bin/"/> 3325 <Reference name="log4net" path="../../../../../bin/"/>
3325 <Reference name="Nini" path="../../../../../bin/"/> 3326 <Reference name="Nini" path="../../../../../bin/"/>
3326 <Reference name="nunit.framework" path="../../../../../bin/"/> 3327 <Reference name="nunit.framework" path="../../../../../bin/"/>
3327 <Reference name="OpenMetaverse" path="../../../../../bin/"/> 3328 <Reference name="OpenMetaverse" path="../../../../../bin/"/>
3328 <Reference name="OpenMetaverseTypes" path="../../../../../bin/"/> 3329 <Reference name="OpenMetaverseTypes" path="../../../../../bin/"/>
3329 <Reference name="OpenMetaverse.StructuredData" path="../../../../../bin/"/> 3330 <Reference name="OpenMetaverse.StructuredData" path="../../../../../bin/"/>
3331 <Reference name="OpenSim.Capabilities"/>
3330 <Reference name="OpenSim.Framework"/> 3332 <Reference name="OpenSim.Framework"/>
3331 <Reference name="OpenSim.Framework.Communications"/> 3333 <Reference name="OpenSim.Framework.Communications"/>
3332 <Reference name="OpenSim.Framework.Monitoring"/> 3334 <Reference name="OpenSim.Framework.Monitoring"/>
@@ -3341,6 +3343,7 @@
3341 <Reference name="OpenSim.Tests.Common"/> 3343 <Reference name="OpenSim.Tests.Common"/>
3342 3344
3343 <Files> 3345 <Files>
3346 <Match path="Tests" pattern="*.cs" recurse="false"/>
3344 <Match path="EventQueue/Tests" pattern="*.cs" recurse="false"/> 3347 <Match path="EventQueue/Tests" pattern="*.cs" recurse="false"/>
3345 </Files> 3348 </Files>
3346 </Project> 3349 </Project>