OpenSim
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Events Macros
ThrottleTests.cs
Go to the documentation of this file.
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 
28 using System;
29 using Nini.Config;
30 using NUnit.Framework;
31 using OpenMetaverse.Packets;
32 using OpenSim.Framework;
33 using OpenSim.Region.Framework.Scenes;
34 using OpenSim.Tests.Common;
35 
36 namespace OpenSim.Region.ClientStack.LindenUDP.Tests
37 {
38  /*
39  [TestFixture]
40  public class ThrottleTests : OpenSimTestCase
41  {
42  [TestFixtureSetUp]
43  public void FixtureInit()
44  {
45  // Don't allow tests to be bamboozled by asynchronous events. Execute everything on the same thread.
46  Util.FireAndForgetMethod = FireAndForgetMethod.RegressionTest;
47  }
48 
49  [TestFixtureTearDown]
50  public void TearDown()
51  {
52  // We must set this back afterwards, otherwise later tests will fail since they're expecting multiple
53  // threads. Possibly, later tests should be rewritten so none of them require async stuff (which regression
54  // tests really shouldn't).
55  Util.FireAndForgetMethod = Util.DefaultFireAndForgetMethod;
56  }
57 
58  [Test]
59  public void TestSetRequestDripRate()
60  {
61 
62  TestHelpers.InMethod();
63 
64  TokenBucket tb = new TokenBucket(null, 5000f,10000f);
65  AssertRates(tb, 5000, 0, 5000, 0);
66 
67  tb.RequestedDripRate = 4000f;
68  AssertRates(tb, 4000, 0, 4000, 0);
69 
70  tb.RequestedDripRate = 6000;
71  AssertRates(tb, 6000, 0, 6000, 0);
72 
73  }
74 
75  [Test]
76  public void TestSetRequestDripRateWithMax()
77  {
78  TestHelpers.InMethod();
79 
80  TokenBucket tb = new TokenBucket(null, 5000,15000);
81  AssertRates(tb, 5000, 0, 5000, 10000);
82 
83  tb.RequestedDripRate = 4000;
84  AssertRates(tb, 4000, 0, 4000, 10000);
85 
86  tb.RequestedDripRate = 6000;
87  AssertRates(tb, 6000, 0, 6000, 10000);
88 
89  tb.RequestedDripRate = 12000;
90  AssertRates(tb, 10000, 0, 10000, 10000);
91  }
92 
93  [Test]
94  public void TestSetRequestDripRateWithChildren()
95  {
96  TestHelpers.InMethod();
97 
98  TokenBucket tbParent = new TokenBucket("tbParent", null, 0);
99  TokenBucket tbChild1 = new TokenBucket("tbChild1", tbParent, 3000);
100  TokenBucket tbChild2 = new TokenBucket("tbChild2", tbParent, 5000);
101 
102  AssertRates(tbParent, 8000, 8000, 8000, 0);
103  AssertRates(tbChild1, 3000, 0, 3000, 0);
104  AssertRates(tbChild2, 5000, 0, 5000, 0);
105 
106  // Test: Setting a parent request greater than total children requests.
107  tbParent.RequestedDripRate = 10000;
108 
109  AssertRates(tbParent, 10000, 8000, 8000, 0);
110  AssertRates(tbChild1, 3000, 0, 3000, 0);
111  AssertRates(tbChild2, 5000, 0, 5000, 0);
112 
113  // Test: Setting a parent request lower than total children requests.
114  tbParent.RequestedDripRate = 6000;
115 
116  AssertRates(tbParent, 6000, 8000, 6000, 0);
117  AssertRates(tbChild1, 3000, 0, 6000 / 8 * 3, 0);
118  AssertRates(tbChild2, 5000, 0, 6000 / 8 * 5, 0);
119 
120  }
121 
122  private void AssertRates(
123  TokenBucket tb, double requestedDripRate, double totalDripRequest, double dripRate, double maxDripRate)
124  {
125  Assert.AreEqual((int)requestedDripRate, tb.RequestedDripRate, "Requested drip rate");
126  Assert.AreEqual((int)totalDripRequest, tb.TotalDripRequest, "Total drip request");
127  Assert.AreEqual((int)dripRate, tb.DripRate, "Drip rate");
128  Assert.AreEqual((int)maxDripRate, tb.MaxDripRate, "Max drip rate");
129  }
130 
131  [Test]
132  public void TestClientThrottleSetNoLimit()
133  {
134  TestHelpers.InMethod();
135 // TestHelpers.EnableLogging();
136 
137  Scene scene = new SceneHelpers().SetupScene();
138  TestLLUDPServer udpServer = ClientStackHelpers.AddUdpServer(scene);
139 
140  ScenePresence sp
141  = ClientStackHelpers.AddChildClient(
142  scene, udpServer, TestHelpers.ParseTail(0x1), TestHelpers.ParseTail(0x2), 123456);
143 
144  LLUDPClient udpClient = ((LLClientView)sp.ControllingClient).UDPClient;
145 
146  udpServer.Throttle.DebugLevel = 1;
147  udpClient.ThrottleDebugLevel = 1;
148 
149  int resendBytes = 1000;
150  int landBytes = 2000;
151  int windBytes = 3000;
152  int cloudBytes = 4000;
153  int taskBytes = 5000;
154  int textureBytes = 6000;
155  int assetBytes = 7000;
156 
157  SetThrottles(
158  udpClient, resendBytes, landBytes, windBytes, cloudBytes, taskBytes, textureBytes, assetBytes);
159 
160  // We expect this to be lower because of the minimum bound set by MTU
161  int totalBytes = LLUDPServer.MTU + landBytes + windBytes + cloudBytes + taskBytes + textureBytes + assetBytes;
162 
163  AssertThrottles(
164  udpClient,
165  LLUDPServer.MTU, landBytes, windBytes, cloudBytes, taskBytes,
166  textureBytes, assetBytes, totalBytes, 0, 0);
167  }
168 
169  [Test]
170  public void TestClientThrottleAdaptiveNoLimit()
171  {
172  TestHelpers.InMethod();
173 // TestHelpers.EnableLogging();
174 
175  Scene scene = new SceneHelpers().SetupScene();
176 
177  IniConfigSource ics = new IniConfigSource();
178  IConfig config = ics.AddConfig("ClientStack.LindenUDP");
179  config.Set("enable_adaptive_throttles", true);
180  config.Set("adaptive_throttle_min_bps", 32000);
181 
182  TestLLUDPServer udpServer = ClientStackHelpers.AddUdpServer(scene, ics);
183 
184  ScenePresence sp
185  = ClientStackHelpers.AddChildClient(
186  scene, udpServer, TestHelpers.ParseTail(0x1), TestHelpers.ParseTail(0x2), 123456);
187 
188  LLUDPClient udpClient = ((LLClientView)sp.ControllingClient).UDPClient;
189 
190  udpServer.Throttle.DebugLevel = 1;
191  udpClient.ThrottleDebugLevel = 1;
192 
193  // Total is 275000
194  int resendBytes = 5000; // this is set low to test the minimum throttle override
195  int landBytes = 20000;
196  int windBytes = 30000;
197  int cloudBytes = 40000;
198  int taskBytes = 50000;
199  int textureBytes = 60000;
200  int assetBytes = 70000;
201  int totalBytes = resendBytes + landBytes + windBytes + cloudBytes + taskBytes + textureBytes + assetBytes;
202 
203  SetThrottles(
204  udpClient, resendBytes, landBytes, windBytes, cloudBytes, taskBytes, textureBytes, assetBytes);
205 
206  // Ratio of current adaptive drip rate to requested bytes, minimum rate is 32000
207  double commitRatio = 32000.0 / totalBytes;
208 
209  AssertThrottles(
210  udpClient,
211  LLUDPServer.MTU, landBytes * commitRatio, windBytes * commitRatio, cloudBytes * commitRatio, taskBytes * commitRatio,
212  textureBytes * commitRatio, assetBytes * commitRatio, udpClient.FlowThrottle.AdjustedDripRate, totalBytes, 0);
213 
214  // Test an increase in target throttle, ack of 20 packets adds 20 * LLUDPServer.MTU bytes
215  // to the throttle, recompute commitratio from those numbers
216  udpClient.FlowThrottle.AcknowledgePackets(20);
217  commitRatio = (32000.0 + 20.0 * LLUDPServer.MTU) / totalBytes;
218 
219  AssertThrottles(
220  udpClient,
221  LLUDPServer.MTU, landBytes * commitRatio, windBytes * commitRatio, cloudBytes * commitRatio, taskBytes * commitRatio,
222  textureBytes * commitRatio, assetBytes * commitRatio, udpClient.FlowThrottle.AdjustedDripRate, totalBytes, 0);
223 
224  // Test a decrease in target throttle, adaptive throttle should cut the rate by 50% with a floor
225  // set by the minimum adaptive rate
226  udpClient.FlowThrottle.ExpirePackets(1);
227  commitRatio = (32000.0 + (20.0 * LLUDPServer.MTU)/Math.Pow(2,1)) / totalBytes;
228 
229  AssertThrottles(
230  udpClient,
231  LLUDPServer.MTU, landBytes * commitRatio, windBytes * commitRatio, cloudBytes * commitRatio, taskBytes * commitRatio,
232  textureBytes * commitRatio, assetBytes * commitRatio, udpClient.FlowThrottle.AdjustedDripRate, totalBytes, 0);
233  }
234 
238  [Test]
239  public void TestSingleClientThrottleRegionLimited()
240  {
241  TestHelpers.InMethod();
242  // TestHelpers.EnableLogging();
243 
244  int resendBytes = 6000;
245  int landBytes = 8000;
246  int windBytes = 10000;
247  int cloudBytes = 12000;
248  int taskBytes = 14000;
249  int textureBytes = 16000;
250  int assetBytes = 18000;
251  int totalBytes
252  = (int)((resendBytes + landBytes + windBytes + cloudBytes + taskBytes + textureBytes + assetBytes) / 2);
253 
254  Scene scene = new SceneHelpers().SetupScene();
255  TestLLUDPServer udpServer = ClientStackHelpers.AddUdpServer(scene);
256  udpServer.Throttle.RequestedDripRate = totalBytes;
257 
258  ScenePresence sp1
259  = ClientStackHelpers.AddChildClient(
260  scene, udpServer, TestHelpers.ParseTail(0x1), TestHelpers.ParseTail(0x2), 123456);
261 
262  LLUDPClient udpClient1 = ((LLClientView)sp1.ControllingClient).UDPClient;
263 
264  SetThrottles(
265  udpClient1, resendBytes, landBytes, windBytes, cloudBytes, taskBytes, textureBytes, assetBytes);
266 
267  AssertThrottles(
268  udpClient1,
269  resendBytes / 2, landBytes / 2, windBytes / 2, cloudBytes / 2, taskBytes / 2,
270  textureBytes / 2, assetBytes / 2, totalBytes, 0, 0);
271 
272  // Test: Now add another client
273  ScenePresence sp2
274  = ClientStackHelpers.AddChildClient(
275  scene, udpServer, TestHelpers.ParseTail(0x10), TestHelpers.ParseTail(0x20), 123457);
276 
277  LLUDPClient udpClient2 = ((LLClientView)sp2.ControllingClient).UDPClient;
278  // udpClient.ThrottleDebugLevel = 1;
279 
280  SetThrottles(
281  udpClient2, resendBytes, landBytes, windBytes, cloudBytes, taskBytes, textureBytes, assetBytes);
282 
283  AssertThrottles(
284  udpClient1,
285  resendBytes / 4, landBytes / 4, windBytes / 4, cloudBytes / 4, taskBytes / 4,
286  textureBytes / 4, assetBytes / 4, totalBytes / 2, 0, 0);
287 
288  AssertThrottles(
289  udpClient2,
290  resendBytes / 4, landBytes / 4, windBytes / 4, cloudBytes / 4, taskBytes / 4,
291  textureBytes / 4, assetBytes / 4, totalBytes / 2, 0, 0);
292  }
293 
297  [Test]
298  public void TestClientThrottlePerClientLimited()
299  {
300  TestHelpers.InMethod();
301  // TestHelpers.EnableLogging();
302 
303  int resendBytes = 4000;
304  int landBytes = 6000;
305  int windBytes = 8000;
306  int cloudBytes = 10000;
307  int taskBytes = 12000;
308  int textureBytes = 14000;
309  int assetBytes = 16000;
310  int totalBytes
311  = (int)((resendBytes + landBytes + windBytes + cloudBytes + taskBytes + textureBytes + assetBytes) / 2);
312 
313  Scene scene = new SceneHelpers().SetupScene();
314  TestLLUDPServer udpServer = ClientStackHelpers.AddUdpServer(scene);
315  udpServer.ThrottleRates.Total = totalBytes;
316 
317  ScenePresence sp
318  = ClientStackHelpers.AddChildClient(
319  scene, udpServer, TestHelpers.ParseTail(0x1), TestHelpers.ParseTail(0x2), 123456);
320 
321  LLUDPClient udpClient = ((LLClientView)sp.ControllingClient).UDPClient;
322  // udpClient.ThrottleDebugLevel = 1;
323 
324  SetThrottles(
325  udpClient, resendBytes, landBytes, windBytes, cloudBytes, taskBytes, textureBytes, assetBytes);
326 
327  AssertThrottles(
328  udpClient,
329  resendBytes / 2, landBytes / 2, windBytes / 2, cloudBytes / 2, taskBytes / 2,
330  textureBytes / 2, assetBytes / 2, totalBytes, 0, totalBytes);
331  }
332 
333  [Test]
334  public void TestClientThrottlePerClientAndRegionLimited()
335  {
336  TestHelpers.InMethod();
337  //TestHelpers.EnableLogging();
338 
339  int resendBytes = 4000;
340  int landBytes = 6000;
341  int windBytes = 8000;
342  int cloudBytes = 10000;
343  int taskBytes = 12000;
344  int textureBytes = 14000;
345  int assetBytes = 16000;
346 
347  // current total 70000
348  int totalBytes = resendBytes + landBytes + windBytes + cloudBytes + taskBytes + textureBytes + assetBytes;
349 
350  Scene scene = new SceneHelpers().SetupScene();
351  TestLLUDPServer udpServer = ClientStackHelpers.AddUdpServer(scene);
352  udpServer.ThrottleRates.Total = (int)(totalBytes * 1.1);
353  udpServer.Throttle.RequestedDripRate = (int)(totalBytes * 1.5);
354 
355  ScenePresence sp1
356  = ClientStackHelpers.AddChildClient(
357  scene, udpServer, TestHelpers.ParseTail(0x1), TestHelpers.ParseTail(0x2), 123456);
358 
359  LLUDPClient udpClient1 = ((LLClientView)sp1.ControllingClient).UDPClient;
360  udpClient1.ThrottleDebugLevel = 1;
361 
362  SetThrottles(
363  udpClient1, resendBytes, landBytes, windBytes, cloudBytes, taskBytes, textureBytes, assetBytes);
364 
365  AssertThrottles(
366  udpClient1,
367  resendBytes, landBytes, windBytes, cloudBytes, taskBytes,
368  textureBytes, assetBytes, totalBytes, 0, totalBytes * 1.1);
369 
370  // Now add another client
371  ScenePresence sp2
372  = ClientStackHelpers.AddChildClient(
373  scene, udpServer, TestHelpers.ParseTail(0x10), TestHelpers.ParseTail(0x20), 123457);
374 
375  LLUDPClient udpClient2 = ((LLClientView)sp2.ControllingClient).UDPClient;
376  udpClient2.ThrottleDebugLevel = 1;
377 
378  SetThrottles(
379  udpClient2, resendBytes, landBytes, windBytes, cloudBytes, taskBytes, textureBytes, assetBytes);
380 
381  AssertThrottles(
382  udpClient1,
383  resendBytes * 0.75, landBytes * 0.75, windBytes * 0.75, cloudBytes * 0.75, taskBytes * 0.75,
384  textureBytes * 0.75, assetBytes * 0.75, totalBytes * 0.75, 0, totalBytes * 1.1);
385 
386  AssertThrottles(
387  udpClient2,
388  resendBytes * 0.75, landBytes * 0.75, windBytes * 0.75, cloudBytes * 0.75, taskBytes * 0.75,
389  textureBytes * 0.75, assetBytes * 0.75, totalBytes * 0.75, 0, totalBytes * 1.1);
390  }
391 
392  private void AssertThrottles(
393  LLUDPClient udpClient,
394  double resendBytes, double landBytes, double windBytes, double cloudBytes, double taskBytes, double textureBytes, double assetBytes,
395  double totalBytes, double targetBytes, double maxBytes)
396  {
397  ClientInfo ci = udpClient.GetClientInfo();
398 
399 // Console.WriteLine(
400 // "Resend={0}, Land={1}, Wind={2}, Cloud={3}, Task={4}, Texture={5}, Asset={6}, TOTAL = {7}",
401 // ci.resendThrottle, ci.landThrottle, ci.windThrottle, ci.cloudThrottle, ci.taskThrottle, ci.textureThrottle, ci.assetThrottle, ci.totalThrottle);
402 
403  Assert.AreEqual((int)resendBytes, ci.resendThrottle, "Resend");
404  Assert.AreEqual((int)landBytes, ci.landThrottle, "Land");
405  Assert.AreEqual((int)windBytes, ci.windThrottle, "Wind");
406  Assert.AreEqual((int)cloudBytes, ci.cloudThrottle, "Cloud");
407  Assert.AreEqual((int)taskBytes, ci.taskThrottle, "Task");
408  Assert.AreEqual((int)textureBytes, ci.textureThrottle, "Texture");
409  Assert.AreEqual((int)assetBytes, ci.assetThrottle, "Asset");
410  Assert.AreEqual((int)totalBytes, ci.totalThrottle, "Total");
411  Assert.AreEqual((int)targetBytes, ci.targetThrottle, "Target");
412  Assert.AreEqual((int)maxBytes, ci.maxThrottle, "Max");
413  }
414 
415  private void SetThrottles(
416  LLUDPClient udpClient, int resendBytes, int landBytes, int windBytes, int cloudBytes, int taskBytes, int textureBytes, int assetBytes)
417  {
418  byte[] throttles = new byte[28];
419 
420  Array.Copy(BitConverter.GetBytes((float)resendBytes * 8), 0, throttles, 0, 4);
421  Array.Copy(BitConverter.GetBytes((float)landBytes * 8), 0, throttles, 4, 4);
422  Array.Copy(BitConverter.GetBytes((float)windBytes * 8), 0, throttles, 8, 4);
423  Array.Copy(BitConverter.GetBytes((float)cloudBytes * 8), 0, throttles, 12, 4);
424  Array.Copy(BitConverter.GetBytes((float)taskBytes * 8), 0, throttles, 16, 4);
425  Array.Copy(BitConverter.GetBytes((float)textureBytes * 8), 0, throttles, 20, 4);
426  Array.Copy(BitConverter.GetBytes((float)assetBytes * 8), 0, throttles, 24, 4);
427 
428  udpClient.SetThrottles(throttles);
429  }
430  }
431  */
432 }