diff options
author | David Walter Seikel | 2016-11-03 21:44:39 +1000 |
---|---|---|
committer | David Walter Seikel | 2016-11-03 21:44:39 +1000 |
commit | 134f86e8d5c414409631b25b8c6f0ee45fbd8631 (patch) | |
tree | 216b89d3fb89acfb81be1e440c25c41ab09fa96d /OpenSim/Region/OptionalModules/Scripting/JsonStore/Tests | |
parent | More changing to production grid. Double oops. (diff) | |
download | opensim-SC-134f86e8d5c414409631b25b8c6f0ee45fbd8631.zip opensim-SC-134f86e8d5c414409631b25b8c6f0ee45fbd8631.tar.gz opensim-SC-134f86e8d5c414409631b25b8c6f0ee45fbd8631.tar.bz2 opensim-SC-134f86e8d5c414409631b25b8c6f0ee45fbd8631.tar.xz |
Initial update to OpenSim 0.8.2.1 source code.
Diffstat (limited to 'OpenSim/Region/OptionalModules/Scripting/JsonStore/Tests')
-rw-r--r-- | OpenSim/Region/OptionalModules/Scripting/JsonStore/Tests/JsonStoreScriptModuleTests.cs | 900 |
1 files changed, 900 insertions, 0 deletions
diff --git a/OpenSim/Region/OptionalModules/Scripting/JsonStore/Tests/JsonStoreScriptModuleTests.cs b/OpenSim/Region/OptionalModules/Scripting/JsonStore/Tests/JsonStoreScriptModuleTests.cs new file mode 100644 index 0000000..99a7076 --- /dev/null +++ b/OpenSim/Region/OptionalModules/Scripting/JsonStore/Tests/JsonStoreScriptModuleTests.cs | |||
@@ -0,0 +1,900 @@ | |||
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 System.Collections.Generic; | ||
30 | using System.Reflection; | ||
31 | using System.Text; | ||
32 | using log4net; | ||
33 | using Nini.Config; | ||
34 | using NUnit.Framework; | ||
35 | using OpenMetaverse; | ||
36 | using OpenSim.Framework; | ||
37 | using OpenSim.Region.CoreModules.Scripting.ScriptModuleComms; | ||
38 | using OpenSim.Region.Framework.Scenes; | ||
39 | using OpenSim.Region.ScriptEngine.Shared; | ||
40 | using OpenSim.Region.ScriptEngine.Shared.Api; | ||
41 | using OpenSim.Services.Interfaces; | ||
42 | using OpenSim.Tests.Common; | ||
43 | |||
44 | namespace OpenSim.Region.OptionalModules.Scripting.JsonStore.Tests | ||
45 | { | ||
46 | /// <summary> | ||
47 | /// Tests for inventory functions in LSL | ||
48 | /// </summary> | ||
49 | [TestFixture] | ||
50 | public class JsonStoreScriptModuleTests : OpenSimTestCase | ||
51 | { | ||
52 | private Scene m_scene; | ||
53 | private MockScriptEngine m_engine; | ||
54 | private ScriptModuleCommsModule m_smcm; | ||
55 | private JsonStoreScriptModule m_jssm; | ||
56 | |||
57 | [TestFixtureSetUp] | ||
58 | public void FixtureInit() | ||
59 | { | ||
60 | // Don't allow tests to be bamboozled by asynchronous events. Execute everything on the same thread. | ||
61 | Util.FireAndForgetMethod = FireAndForgetMethod.RegressionTest; | ||
62 | } | ||
63 | |||
64 | [TestFixtureTearDown] | ||
65 | public void TearDown() | ||
66 | { | ||
67 | // We must set this back afterwards, otherwise later tests will fail since they're expecting multiple | ||
68 | // threads. Possibly, later tests should be rewritten so none of them require async stuff (which regression | ||
69 | // tests really shouldn't). | ||
70 | Util.FireAndForgetMethod = Util.DefaultFireAndForgetMethod; | ||
71 | } | ||
72 | |||
73 | [SetUp] | ||
74 | public override void SetUp() | ||
75 | { | ||
76 | base.SetUp(); | ||
77 | |||
78 | IConfigSource configSource = new IniConfigSource(); | ||
79 | IConfig jsonStoreConfig = configSource.AddConfig("JsonStore"); | ||
80 | jsonStoreConfig.Set("Enabled", "true"); | ||
81 | |||
82 | m_engine = new MockScriptEngine(); | ||
83 | m_smcm = new ScriptModuleCommsModule(); | ||
84 | JsonStoreModule jsm = new JsonStoreModule(); | ||
85 | m_jssm = new JsonStoreScriptModule(); | ||
86 | |||
87 | m_scene = new SceneHelpers().SetupScene(); | ||
88 | SceneHelpers.SetupSceneModules(m_scene, configSource, m_engine, m_smcm, jsm, m_jssm); | ||
89 | |||
90 | try | ||
91 | { | ||
92 | m_smcm.RegisterScriptInvocation(this, "DummyTestMethod"); | ||
93 | } | ||
94 | catch (ArgumentException) | ||
95 | { | ||
96 | Assert.Ignore("Ignoring test since running on .NET 3.5 or earlier."); | ||
97 | } | ||
98 | |||
99 | // XXX: Unfortunately, ICommsModule currently has no way of deregistering methods. | ||
100 | } | ||
101 | |||
102 | private object InvokeOp(string name, params object[] args) | ||
103 | { | ||
104 | return InvokeOpOnHost(name, UUID.Zero, args); | ||
105 | } | ||
106 | |||
107 | private object InvokeOpOnHost(string name, UUID hostId, params object[] args) | ||
108 | { | ||
109 | return m_smcm.InvokeOperation(hostId, UUID.Zero, name, args); | ||
110 | } | ||
111 | |||
112 | [Test] | ||
113 | public void TestJsonCreateStore() | ||
114 | { | ||
115 | TestHelpers.InMethod(); | ||
116 | // TestHelpers.EnableLogging(); | ||
117 | |||
118 | // Test blank store | ||
119 | { | ||
120 | UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{}"); | ||
121 | Assert.That(storeId, Is.Not.EqualTo(UUID.Zero)); | ||
122 | } | ||
123 | |||
124 | // Test single element store | ||
125 | { | ||
126 | UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{ 'Hello' : 'World' }"); | ||
127 | Assert.That(storeId, Is.Not.EqualTo(UUID.Zero)); | ||
128 | } | ||
129 | |||
130 | // Test with an integer value | ||
131 | { | ||
132 | UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{ 'Hello' : 42.15 }"); | ||
133 | Assert.That(storeId, Is.Not.EqualTo(UUID.Zero)); | ||
134 | |||
135 | string value = (string)InvokeOp("JsonGetValue", storeId, "Hello"); | ||
136 | Assert.That(value, Is.EqualTo("42.15")); | ||
137 | } | ||
138 | |||
139 | // Test with an array as the root node | ||
140 | { | ||
141 | UUID storeId = (UUID)InvokeOp("JsonCreateStore", "[ 'one', 'two', 'three' ]"); | ||
142 | Assert.That(storeId, Is.Not.EqualTo(UUID.Zero)); | ||
143 | |||
144 | string value = (string)InvokeOp("JsonGetValue", storeId, "[1]"); | ||
145 | Assert.That(value, Is.EqualTo("two")); | ||
146 | } | ||
147 | } | ||
148 | |||
149 | [Test] | ||
150 | public void TestJsonDestroyStore() | ||
151 | { | ||
152 | TestHelpers.InMethod(); | ||
153 | // TestHelpers.EnableLogging(); | ||
154 | |||
155 | UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{ 'Hello' : 'World' }"); | ||
156 | int dsrv = (int)InvokeOp("JsonDestroyStore", storeId); | ||
157 | |||
158 | Assert.That(dsrv, Is.EqualTo(1)); | ||
159 | |||
160 | int tprv = (int)InvokeOp("JsonGetNodeType", storeId, "Hello"); | ||
161 | Assert.That(tprv, Is.EqualTo(JsonStoreScriptModule.JSON_NODETYPE_UNDEF)); | ||
162 | } | ||
163 | |||
164 | [Test] | ||
165 | public void TestJsonDestroyStoreNotExists() | ||
166 | { | ||
167 | TestHelpers.InMethod(); | ||
168 | // TestHelpers.EnableLogging(); | ||
169 | |||
170 | UUID fakeStoreId = TestHelpers.ParseTail(0x500); | ||
171 | |||
172 | int dsrv = (int)InvokeOp("JsonDestroyStore", fakeStoreId); | ||
173 | |||
174 | Assert.That(dsrv, Is.EqualTo(0)); | ||
175 | } | ||
176 | |||
177 | [Test] | ||
178 | public void TestJsonGetValue() | ||
179 | { | ||
180 | TestHelpers.InMethod(); | ||
181 | // TestHelpers.EnableLogging(); | ||
182 | |||
183 | UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{ 'Hello' : { 'World' : 'Two' } }"); | ||
184 | |||
185 | { | ||
186 | string value = (string)InvokeOp("JsonGetValue", storeId, "Hello.World"); | ||
187 | Assert.That(value, Is.EqualTo("Two")); | ||
188 | } | ||
189 | |||
190 | // Test get of path section instead of leaf | ||
191 | { | ||
192 | string value = (string)InvokeOp("JsonGetValue", storeId, "Hello"); | ||
193 | Assert.That(value, Is.EqualTo("")); | ||
194 | } | ||
195 | |||
196 | // Test get of non-existing value | ||
197 | { | ||
198 | string fakeValueGet = (string)InvokeOp("JsonGetValue", storeId, "foo"); | ||
199 | Assert.That(fakeValueGet, Is.EqualTo("")); | ||
200 | } | ||
201 | |||
202 | // Test get from non-existing store | ||
203 | { | ||
204 | UUID fakeStoreId = TestHelpers.ParseTail(0x500); | ||
205 | string fakeStoreValueGet = (string)InvokeOp("JsonGetValue", fakeStoreId, "Hello"); | ||
206 | Assert.That(fakeStoreValueGet, Is.EqualTo("")); | ||
207 | } | ||
208 | } | ||
209 | |||
210 | [Test] | ||
211 | public void TestJsonGetJson() | ||
212 | { | ||
213 | TestHelpers.InMethod(); | ||
214 | // TestHelpers.EnableLogging(); | ||
215 | |||
216 | UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{ 'Hello' : { 'World' : 'Two' } }"); | ||
217 | |||
218 | { | ||
219 | string value = (string)InvokeOp("JsonGetJson", storeId, "Hello.World"); | ||
220 | Assert.That(value, Is.EqualTo("'Two'")); | ||
221 | } | ||
222 | |||
223 | // Test get of path section instead of leaf | ||
224 | { | ||
225 | string value = (string)InvokeOp("JsonGetJson", storeId, "Hello"); | ||
226 | Assert.That(value, Is.EqualTo("{\"World\":\"Two\"}")); | ||
227 | } | ||
228 | |||
229 | // Test get of non-existing value | ||
230 | { | ||
231 | string fakeValueGet = (string)InvokeOp("JsonGetJson", storeId, "foo"); | ||
232 | Assert.That(fakeValueGet, Is.EqualTo("")); | ||
233 | } | ||
234 | |||
235 | // Test get from non-existing store | ||
236 | { | ||
237 | UUID fakeStoreId = TestHelpers.ParseTail(0x500); | ||
238 | string fakeStoreValueGet = (string)InvokeOp("JsonGetJson", fakeStoreId, "Hello"); | ||
239 | Assert.That(fakeStoreValueGet, Is.EqualTo("")); | ||
240 | } | ||
241 | } | ||
242 | |||
243 | // [Test] | ||
244 | // public void TestJsonTakeValue() | ||
245 | // { | ||
246 | // TestHelpers.InMethod(); | ||
247 | //// TestHelpers.EnableLogging(); | ||
248 | // | ||
249 | // UUID storeId | ||
250 | // = (UUID)m_smcm.InvokeOperation( | ||
251 | // UUID.Zero, UUID.Zero, "JsonCreateStore", new object[] { "{ 'Hello' : 'World' }" }); | ||
252 | // | ||
253 | // string value | ||
254 | // = (string)m_smcm.InvokeOperation( | ||
255 | // UUID.Zero, UUID.Zero, "JsonTakeValue", new object[] { storeId, "Hello" }); | ||
256 | // | ||
257 | // Assert.That(value, Is.EqualTo("World")); | ||
258 | // | ||
259 | // string value2 | ||
260 | // = (string)m_smcm.InvokeOperation( | ||
261 | // UUID.Zero, UUID.Zero, "JsonGetValue", new object[] { storeId, "Hello" }); | ||
262 | // | ||
263 | // Assert.That(value, Is.Null); | ||
264 | // } | ||
265 | |||
266 | [Test] | ||
267 | public void TestJsonRemoveValue() | ||
268 | { | ||
269 | TestHelpers.InMethod(); | ||
270 | // TestHelpers.EnableLogging(); | ||
271 | |||
272 | // Test remove of node in object pointing to a string | ||
273 | { | ||
274 | UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{ 'Hello' : 'World' }"); | ||
275 | |||
276 | int returnValue = (int)InvokeOp( "JsonRemoveValue", storeId, "Hello"); | ||
277 | Assert.That(returnValue, Is.EqualTo(1)); | ||
278 | |||
279 | int result = (int)InvokeOp("JsonGetNodeType", storeId, "Hello"); | ||
280 | Assert.That(result, Is.EqualTo(JsonStoreScriptModule.JSON_NODETYPE_UNDEF)); | ||
281 | |||
282 | string returnValue2 = (string)InvokeOp("JsonGetValue", storeId, "Hello"); | ||
283 | Assert.That(returnValue2, Is.EqualTo("")); | ||
284 | } | ||
285 | |||
286 | // Test remove of node in object pointing to another object | ||
287 | { | ||
288 | UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{ 'Hello' : { 'World' : 'Wally' } }"); | ||
289 | |||
290 | int returnValue = (int)InvokeOp( "JsonRemoveValue", storeId, "Hello"); | ||
291 | Assert.That(returnValue, Is.EqualTo(1)); | ||
292 | |||
293 | int result = (int)InvokeOp("JsonGetNodeType", storeId, "Hello"); | ||
294 | Assert.That(result, Is.EqualTo(JsonStoreScriptModule.JSON_NODETYPE_UNDEF)); | ||
295 | |||
296 | string returnValue2 = (string)InvokeOp("JsonGetJson", storeId, "Hello"); | ||
297 | Assert.That(returnValue2, Is.EqualTo("")); | ||
298 | } | ||
299 | |||
300 | // Test remove of node in an array | ||
301 | { | ||
302 | UUID storeId | ||
303 | = (UUID)InvokeOp("JsonCreateStore", "{ 'Hello' : [ 'value1', 'value2' ] }"); | ||
304 | |||
305 | int returnValue = (int)InvokeOp( "JsonRemoveValue", storeId, "Hello[0]"); | ||
306 | Assert.That(returnValue, Is.EqualTo(1)); | ||
307 | |||
308 | int result = (int)InvokeOp("JsonGetNodeType", storeId, "Hello[0]"); | ||
309 | Assert.That(result, Is.EqualTo(JsonStoreScriptModule.JSON_NODETYPE_VALUE)); | ||
310 | |||
311 | result = (int)InvokeOp("JsonGetNodeType", storeId, "Hello[1]"); | ||
312 | Assert.That(result, Is.EqualTo(JsonStoreScriptModule.JSON_NODETYPE_UNDEF)); | ||
313 | |||
314 | string stringReturnValue = (string)InvokeOp("JsonGetValue", storeId, "Hello[0]"); | ||
315 | Assert.That(stringReturnValue, Is.EqualTo("value2")); | ||
316 | |||
317 | stringReturnValue = (string)InvokeOp("JsonGetJson", storeId, "Hello[1]"); | ||
318 | Assert.That(stringReturnValue, Is.EqualTo("")); | ||
319 | } | ||
320 | |||
321 | // Test remove of non-existing value | ||
322 | { | ||
323 | UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{ 'Hello' : 'World' }"); | ||
324 | |||
325 | int fakeValueRemove = (int)InvokeOp("JsonRemoveValue", storeId, "Cheese"); | ||
326 | Assert.That(fakeValueRemove, Is.EqualTo(0)); | ||
327 | } | ||
328 | |||
329 | { | ||
330 | // Test get from non-existing store | ||
331 | UUID fakeStoreId = TestHelpers.ParseTail(0x500); | ||
332 | int fakeStoreValueRemove = (int)InvokeOp("JsonRemoveValue", fakeStoreId, "Hello"); | ||
333 | Assert.That(fakeStoreValueRemove, Is.EqualTo(0)); | ||
334 | } | ||
335 | } | ||
336 | |||
337 | // [Test] | ||
338 | // public void TestJsonTestPath() | ||
339 | // { | ||
340 | // TestHelpers.InMethod(); | ||
341 | //// TestHelpers.EnableLogging(); | ||
342 | // | ||
343 | // UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{ 'Hello' : { 'World' : 'One' } }"); | ||
344 | // | ||
345 | // { | ||
346 | // int result = (int)InvokeOp("JsonTestPath", storeId, "Hello.World"); | ||
347 | // Assert.That(result, Is.EqualTo(1)); | ||
348 | // } | ||
349 | // | ||
350 | // // Test for path which does not resolve to a value. | ||
351 | // { | ||
352 | // int result = (int)InvokeOp("JsonTestPath", storeId, "Hello"); | ||
353 | // Assert.That(result, Is.EqualTo(0)); | ||
354 | // } | ||
355 | // | ||
356 | // { | ||
357 | // int result2 = (int)InvokeOp("JsonTestPath", storeId, "foo"); | ||
358 | // Assert.That(result2, Is.EqualTo(0)); | ||
359 | // } | ||
360 | // | ||
361 | // // Test with fake store | ||
362 | // { | ||
363 | // UUID fakeStoreId = TestHelpers.ParseTail(0x500); | ||
364 | // int fakeStoreValueRemove = (int)InvokeOp("JsonTestPath", fakeStoreId, "Hello"); | ||
365 | // Assert.That(fakeStoreValueRemove, Is.EqualTo(0)); | ||
366 | // } | ||
367 | // } | ||
368 | |||
369 | // [Test] | ||
370 | // public void TestJsonTestPathJson() | ||
371 | // { | ||
372 | // TestHelpers.InMethod(); | ||
373 | //// TestHelpers.EnableLogging(); | ||
374 | // | ||
375 | // UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{ 'Hello' : { 'World' : 'One' } }"); | ||
376 | // | ||
377 | // { | ||
378 | // int result = (int)InvokeOp("JsonTestPathJson", storeId, "Hello.World"); | ||
379 | // Assert.That(result, Is.EqualTo(1)); | ||
380 | // } | ||
381 | // | ||
382 | // // Test for path which does not resolve to a value. | ||
383 | // { | ||
384 | // int result = (int)InvokeOp("JsonTestPathJson", storeId, "Hello"); | ||
385 | // Assert.That(result, Is.EqualTo(1)); | ||
386 | // } | ||
387 | // | ||
388 | // { | ||
389 | // int result2 = (int)InvokeOp("JsonTestPathJson", storeId, "foo"); | ||
390 | // Assert.That(result2, Is.EqualTo(0)); | ||
391 | // } | ||
392 | // | ||
393 | // // Test with fake store | ||
394 | // { | ||
395 | // UUID fakeStoreId = TestHelpers.ParseTail(0x500); | ||
396 | // int fakeStoreValueRemove = (int)InvokeOp("JsonTestPathJson", fakeStoreId, "Hello"); | ||
397 | // Assert.That(fakeStoreValueRemove, Is.EqualTo(0)); | ||
398 | // } | ||
399 | // } | ||
400 | |||
401 | [Test] | ||
402 | public void TestJsonGetArrayLength() | ||
403 | { | ||
404 | TestHelpers.InMethod(); | ||
405 | // TestHelpers.EnableLogging(); | ||
406 | |||
407 | UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{ 'Hello' : { 'World' : [ 'one', 2 ] } }"); | ||
408 | |||
409 | { | ||
410 | int result = (int)InvokeOp("JsonGetArrayLength", storeId, "Hello.World"); | ||
411 | Assert.That(result, Is.EqualTo(2)); | ||
412 | } | ||
413 | |||
414 | // Test path which is not an array | ||
415 | { | ||
416 | int result = (int)InvokeOp("JsonGetArrayLength", storeId, "Hello"); | ||
417 | Assert.That(result, Is.EqualTo(-1)); | ||
418 | } | ||
419 | |||
420 | // Test fake path | ||
421 | { | ||
422 | int result = (int)InvokeOp("JsonGetArrayLength", storeId, "foo"); | ||
423 | Assert.That(result, Is.EqualTo(-1)); | ||
424 | } | ||
425 | |||
426 | // Test fake store | ||
427 | { | ||
428 | UUID fakeStoreId = TestHelpers.ParseTail(0x500); | ||
429 | int result = (int)InvokeOp("JsonGetArrayLength", fakeStoreId, "Hello.World"); | ||
430 | Assert.That(result, Is.EqualTo(-1)); | ||
431 | } | ||
432 | } | ||
433 | |||
434 | [Test] | ||
435 | public void TestJsonGetNodeType() | ||
436 | { | ||
437 | TestHelpers.InMethod(); | ||
438 | // TestHelpers.EnableLogging(); | ||
439 | |||
440 | UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{ 'Hello' : { 'World' : [ 'one', 2 ] } }"); | ||
441 | |||
442 | { | ||
443 | int result = (int)InvokeOp("JsonGetNodeType", storeId, "."); | ||
444 | Assert.That(result, Is.EqualTo(JsonStoreScriptModule.JSON_NODETYPE_OBJECT)); | ||
445 | } | ||
446 | |||
447 | { | ||
448 | int result = (int)InvokeOp("JsonGetNodeType", storeId, "Hello"); | ||
449 | Assert.That(result, Is.EqualTo(JsonStoreScriptModule.JSON_NODETYPE_OBJECT)); | ||
450 | } | ||
451 | |||
452 | { | ||
453 | int result = (int)InvokeOp("JsonGetNodeType", storeId, "Hello.World"); | ||
454 | Assert.That(result, Is.EqualTo(JsonStoreScriptModule.JSON_NODETYPE_ARRAY)); | ||
455 | } | ||
456 | |||
457 | { | ||
458 | int result = (int)InvokeOp("JsonGetNodeType", storeId, "Hello.World[0]"); | ||
459 | Assert.That(result, Is.EqualTo(JsonStoreScriptModule.JSON_NODETYPE_VALUE)); | ||
460 | } | ||
461 | |||
462 | { | ||
463 | int result = (int)InvokeOp("JsonGetNodeType", storeId, "Hello.World[1]"); | ||
464 | Assert.That(result, Is.EqualTo(JsonStoreScriptModule.JSON_NODETYPE_VALUE)); | ||
465 | } | ||
466 | |||
467 | // Test for non-existent path | ||
468 | { | ||
469 | int result = (int)InvokeOp("JsonGetNodeType", storeId, "foo"); | ||
470 | Assert.That(result, Is.EqualTo(JsonStoreScriptModule.JSON_NODETYPE_UNDEF)); | ||
471 | } | ||
472 | |||
473 | // Test for non-existent store | ||
474 | { | ||
475 | UUID fakeStoreId = TestHelpers.ParseTail(0x500); | ||
476 | int result = (int)InvokeOp("JsonGetNodeType", fakeStoreId, "."); | ||
477 | Assert.That(result, Is.EqualTo(JsonStoreScriptModule.JSON_NODETYPE_UNDEF)); | ||
478 | } | ||
479 | } | ||
480 | |||
481 | [Test] | ||
482 | public void TestJsonList2Path() | ||
483 | { | ||
484 | TestHelpers.InMethod(); | ||
485 | // TestHelpers.EnableLogging(); | ||
486 | |||
487 | // Invoking these methods directly since I just couldn't get comms module invocation to work for some reason | ||
488 | // - some confusion with the methods that take a params object[] invocation. | ||
489 | { | ||
490 | string result = m_jssm.JsonList2Path(UUID.Zero, UUID.Zero, new object[] { "foo" }); | ||
491 | Assert.That(result, Is.EqualTo("{foo}")); | ||
492 | } | ||
493 | |||
494 | { | ||
495 | string result = m_jssm.JsonList2Path(UUID.Zero, UUID.Zero, new object[] { "foo", "bar" }); | ||
496 | Assert.That(result, Is.EqualTo("{foo}.{bar}")); | ||
497 | } | ||
498 | |||
499 | { | ||
500 | string result = m_jssm.JsonList2Path(UUID.Zero, UUID.Zero, new object[] { "foo", 1, "bar" }); | ||
501 | Assert.That(result, Is.EqualTo("{foo}.[1].{bar}")); | ||
502 | } | ||
503 | } | ||
504 | |||
505 | [Test] | ||
506 | public void TestJsonSetValue() | ||
507 | { | ||
508 | TestHelpers.InMethod(); | ||
509 | // TestHelpers.EnableLogging(); | ||
510 | |||
511 | { | ||
512 | UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{}"); | ||
513 | |||
514 | int result = (int)InvokeOp("JsonSetValue", storeId, "Fun", "Times"); | ||
515 | Assert.That(result, Is.EqualTo(1)); | ||
516 | |||
517 | string value = (string)InvokeOp("JsonGetValue", storeId, "Fun"); | ||
518 | Assert.That(value, Is.EqualTo("Times")); | ||
519 | } | ||
520 | |||
521 | // Test setting a key containing periods with delineation | ||
522 | { | ||
523 | UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{}"); | ||
524 | |||
525 | int result = (int)InvokeOp("JsonSetValue", storeId, "{Fun.Circus}", "Times"); | ||
526 | Assert.That(result, Is.EqualTo(1)); | ||
527 | |||
528 | string value = (string)InvokeOp("JsonGetValue", storeId, "{Fun.Circus}"); | ||
529 | Assert.That(value, Is.EqualTo("Times")); | ||
530 | } | ||
531 | |||
532 | // *** Test [] *** | ||
533 | |||
534 | // Test setting a key containing unbalanced ] without delineation. Expecting failure | ||
535 | { | ||
536 | UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{}"); | ||
537 | |||
538 | int result = (int)InvokeOp("JsonSetValue", storeId, "Fun]Circus", "Times"); | ||
539 | Assert.That(result, Is.EqualTo(0)); | ||
540 | |||
541 | string value = (string)InvokeOp("JsonGetValue", storeId, "Fun]Circus"); | ||
542 | Assert.That(value, Is.EqualTo("")); | ||
543 | } | ||
544 | |||
545 | // Test setting a key containing unbalanced [ without delineation. Expecting failure | ||
546 | { | ||
547 | UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{}"); | ||
548 | |||
549 | int result = (int)InvokeOp("JsonSetValue", storeId, "Fun[Circus", "Times"); | ||
550 | Assert.That(result, Is.EqualTo(0)); | ||
551 | |||
552 | string value = (string)InvokeOp("JsonGetValue", storeId, "Fun[Circus"); | ||
553 | Assert.That(value, Is.EqualTo("")); | ||
554 | } | ||
555 | |||
556 | // Test setting a key containing unbalanced [] without delineation. Expecting failure | ||
557 | { | ||
558 | UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{}"); | ||
559 | |||
560 | int result = (int)InvokeOp("JsonSetValue", storeId, "Fun[]Circus", "Times"); | ||
561 | Assert.That(result, Is.EqualTo(0)); | ||
562 | |||
563 | string value = (string)InvokeOp("JsonGetValue", storeId, "Fun[]Circus"); | ||
564 | Assert.That(value, Is.EqualTo("")); | ||
565 | } | ||
566 | |||
567 | // Test setting a key containing unbalanced ] with delineation | ||
568 | { | ||
569 | UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{}"); | ||
570 | |||
571 | int result = (int)InvokeOp("JsonSetValue", storeId, "{Fun]Circus}", "Times"); | ||
572 | Assert.That(result, Is.EqualTo(1)); | ||
573 | |||
574 | string value = (string)InvokeOp("JsonGetValue", storeId, "{Fun]Circus}"); | ||
575 | Assert.That(value, Is.EqualTo("Times")); | ||
576 | } | ||
577 | |||
578 | // Test setting a key containing unbalanced [ with delineation | ||
579 | { | ||
580 | UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{}"); | ||
581 | |||
582 | int result = (int)InvokeOp("JsonSetValue", storeId, "{Fun[Circus}", "Times"); | ||
583 | Assert.That(result, Is.EqualTo(1)); | ||
584 | |||
585 | string value = (string)InvokeOp("JsonGetValue", storeId, "{Fun[Circus}"); | ||
586 | Assert.That(value, Is.EqualTo("Times")); | ||
587 | } | ||
588 | |||
589 | // Test setting a key containing empty balanced [] with delineation | ||
590 | { | ||
591 | UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{}"); | ||
592 | |||
593 | int result = (int)InvokeOp("JsonSetValue", storeId, "{Fun[]Circus}", "Times"); | ||
594 | Assert.That(result, Is.EqualTo(1)); | ||
595 | |||
596 | string value = (string)InvokeOp("JsonGetValue", storeId, "{Fun[]Circus}"); | ||
597 | Assert.That(value, Is.EqualTo("Times")); | ||
598 | } | ||
599 | |||
600 | // // Commented out as this currently unexpectedly fails. | ||
601 | // // Test setting a key containing brackets around an integer with delineation | ||
602 | // { | ||
603 | // UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{}"); | ||
604 | // | ||
605 | // int result = (int)InvokeOp("JsonSetValue", storeId, "{Fun[0]Circus}", "Times"); | ||
606 | // Assert.That(result, Is.EqualTo(1)); | ||
607 | // | ||
608 | // string value = (string)InvokeOp("JsonGetValue", storeId, "{Fun[0]Circus}"); | ||
609 | // Assert.That(value, Is.EqualTo("Times")); | ||
610 | // } | ||
611 | |||
612 | // *** Test {} *** | ||
613 | |||
614 | // Test setting a key containing unbalanced } without delineation. Expecting failure (?) | ||
615 | { | ||
616 | UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{}"); | ||
617 | |||
618 | int result = (int)InvokeOp("JsonSetValue", storeId, "Fun}Circus", "Times"); | ||
619 | Assert.That(result, Is.EqualTo(0)); | ||
620 | |||
621 | string value = (string)InvokeOp("JsonGetValue", storeId, "Fun}Circus"); | ||
622 | Assert.That(value, Is.EqualTo("")); | ||
623 | } | ||
624 | |||
625 | // Test setting a key containing unbalanced { without delineation. Expecting failure (?) | ||
626 | { | ||
627 | UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{}"); | ||
628 | |||
629 | int result = (int)InvokeOp("JsonSetValue", storeId, "Fun{Circus", "Times"); | ||
630 | Assert.That(result, Is.EqualTo(0)); | ||
631 | |||
632 | string value = (string)InvokeOp("JsonGetValue", storeId, "Fun}Circus"); | ||
633 | Assert.That(value, Is.EqualTo("")); | ||
634 | } | ||
635 | |||
636 | // // Commented out as this currently unexpectedly fails. | ||
637 | // // Test setting a key containing unbalanced } | ||
638 | // { | ||
639 | // UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{}"); | ||
640 | // | ||
641 | // int result = (int)InvokeOp("JsonSetValue", storeId, "{Fun}Circus}", "Times"); | ||
642 | // Assert.That(result, Is.EqualTo(0)); | ||
643 | // } | ||
644 | |||
645 | // Test setting a key containing unbalanced { with delineation | ||
646 | { | ||
647 | UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{}"); | ||
648 | |||
649 | int result = (int)InvokeOp("JsonSetValue", storeId, "{Fun{Circus}", "Times"); | ||
650 | Assert.That(result, Is.EqualTo(1)); | ||
651 | |||
652 | string value = (string)InvokeOp("JsonGetValue", storeId, "{Fun{Circus}"); | ||
653 | Assert.That(value, Is.EqualTo("Times")); | ||
654 | } | ||
655 | |||
656 | // Test setting a key containing balanced {} with delineation. This should fail. | ||
657 | { | ||
658 | UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{}"); | ||
659 | |||
660 | int result = (int)InvokeOp("JsonSetValue", storeId, "{Fun{Filled}Circus}", "Times"); | ||
661 | Assert.That(result, Is.EqualTo(0)); | ||
662 | |||
663 | string value = (string)InvokeOp("JsonGetValue", storeId, "{Fun{Filled}Circus}"); | ||
664 | Assert.That(value, Is.EqualTo("")); | ||
665 | } | ||
666 | |||
667 | // Test setting to location that does not exist. This should fail. | ||
668 | { | ||
669 | UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{}"); | ||
670 | |||
671 | int result = (int)InvokeOp("JsonSetValue", storeId, "Fun.Circus", "Times"); | ||
672 | Assert.That(result, Is.EqualTo(0)); | ||
673 | |||
674 | string value = (string)InvokeOp("JsonGetValue", storeId, "Fun.Circus"); | ||
675 | Assert.That(value, Is.EqualTo("")); | ||
676 | } | ||
677 | |||
678 | // Test with fake store | ||
679 | { | ||
680 | UUID fakeStoreId = TestHelpers.ParseTail(0x500); | ||
681 | int fakeStoreValueSet = (int)InvokeOp("JsonSetValue", fakeStoreId, "Hello", "World"); | ||
682 | Assert.That(fakeStoreValueSet, Is.EqualTo(0)); | ||
683 | } | ||
684 | } | ||
685 | |||
686 | [Test] | ||
687 | public void TestJsonSetJson() | ||
688 | { | ||
689 | TestHelpers.InMethod(); | ||
690 | // TestHelpers.EnableLogging(); | ||
691 | |||
692 | // Single quoted token case | ||
693 | { | ||
694 | UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{ }"); | ||
695 | |||
696 | int result = (int)InvokeOp("JsonSetJson", storeId, "Fun", "'Times'"); | ||
697 | Assert.That(result, Is.EqualTo(1)); | ||
698 | |||
699 | string value = (string)InvokeOp("JsonGetValue", storeId, "Fun"); | ||
700 | Assert.That(value, Is.EqualTo("Times")); | ||
701 | } | ||
702 | |||
703 | // Sub-tree case | ||
704 | { | ||
705 | UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{ }"); | ||
706 | |||
707 | int result = (int)InvokeOp("JsonSetJson", storeId, "Fun", "{ 'Filled' : 'Times' }"); | ||
708 | Assert.That(result, Is.EqualTo(1)); | ||
709 | |||
710 | string value = (string)InvokeOp("JsonGetValue", storeId, "Fun.Filled"); | ||
711 | Assert.That(value, Is.EqualTo("Times")); | ||
712 | } | ||
713 | |||
714 | // If setting single strings in JsonSetValueJson, these must be single quoted tokens, not bare strings. | ||
715 | { | ||
716 | UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{ }"); | ||
717 | |||
718 | int result = (int)InvokeOp("JsonSetJson", storeId, "Fun", "Times"); | ||
719 | Assert.That(result, Is.EqualTo(0)); | ||
720 | |||
721 | string value = (string)InvokeOp("JsonGetValue", storeId, "Fun"); | ||
722 | Assert.That(value, Is.EqualTo("")); | ||
723 | } | ||
724 | |||
725 | // Test setting to location that does not exist. This should fail. | ||
726 | { | ||
727 | UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{ }"); | ||
728 | |||
729 | int result = (int)InvokeOp("JsonSetJson", storeId, "Fun.Circus", "'Times'"); | ||
730 | Assert.That(result, Is.EqualTo(0)); | ||
731 | |||
732 | string value = (string)InvokeOp("JsonGetValue", storeId, "Fun.Circus"); | ||
733 | Assert.That(value, Is.EqualTo("")); | ||
734 | } | ||
735 | |||
736 | // Test with fake store | ||
737 | { | ||
738 | UUID fakeStoreId = TestHelpers.ParseTail(0x500); | ||
739 | int fakeStoreValueSet = (int)InvokeOp("JsonSetJson", fakeStoreId, "Hello", "'World'"); | ||
740 | Assert.That(fakeStoreValueSet, Is.EqualTo(0)); | ||
741 | } | ||
742 | } | ||
743 | |||
744 | /// <summary> | ||
745 | /// Test for writing json to a notecard | ||
746 | /// </summary> | ||
747 | /// <remarks> | ||
748 | /// TODO: Really needs to test correct receipt of the link_message event. Could do this by directly fetching | ||
749 | /// it via the MockScriptEngine or perhaps by a dummy script instance. | ||
750 | /// </remarks> | ||
751 | [Test] | ||
752 | public void TestJsonWriteNotecard() | ||
753 | { | ||
754 | TestHelpers.InMethod(); | ||
755 | // TestHelpers.EnableLogging(); | ||
756 | |||
757 | SceneObjectGroup so = SceneHelpers.CreateSceneObject(1, TestHelpers.ParseTail(0x1)); | ||
758 | m_scene.AddSceneObject(so); | ||
759 | |||
760 | UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{ 'Hello':'World' }"); | ||
761 | |||
762 | { | ||
763 | string notecardName = "nc1"; | ||
764 | |||
765 | // Write notecard | ||
766 | UUID writeNotecardRequestId = (UUID)InvokeOpOnHost("JsonWriteNotecard", so.UUID, storeId, "", notecardName); | ||
767 | Assert.That(writeNotecardRequestId, Is.Not.EqualTo(UUID.Zero)); | ||
768 | |||
769 | TaskInventoryItem nc1Item = so.RootPart.Inventory.GetInventoryItem(notecardName); | ||
770 | Assert.That(nc1Item, Is.Not.Null); | ||
771 | |||
772 | // TODO: Should independently check the contents. | ||
773 | } | ||
774 | |||
775 | // TODO: Write partial test | ||
776 | |||
777 | { | ||
778 | // Try to write notecard for a bad path | ||
779 | // In this case we do get a request id but no notecard is written. | ||
780 | string badPathNotecardName = "badPathNotecardName"; | ||
781 | |||
782 | UUID writeNotecardBadPathRequestId | ||
783 | = (UUID)InvokeOpOnHost("JsonWriteNotecard", so.UUID, storeId, "flibble", badPathNotecardName); | ||
784 | Assert.That(writeNotecardBadPathRequestId, Is.Not.EqualTo(UUID.Zero)); | ||
785 | |||
786 | TaskInventoryItem badPathItem = so.RootPart.Inventory.GetInventoryItem(badPathNotecardName); | ||
787 | Assert.That(badPathItem, Is.Null); | ||
788 | } | ||
789 | |||
790 | { | ||
791 | // Test with fake store | ||
792 | // In this case we do get a request id but no notecard is written. | ||
793 | string fakeStoreNotecardName = "fakeStoreNotecardName"; | ||
794 | |||
795 | UUID fakeStoreId = TestHelpers.ParseTail(0x500); | ||
796 | UUID fakeStoreWriteNotecardValue | ||
797 | = (UUID)InvokeOpOnHost("JsonWriteNotecard", so.UUID, fakeStoreId, "", fakeStoreNotecardName); | ||
798 | Assert.That(fakeStoreWriteNotecardValue, Is.Not.EqualTo(UUID.Zero)); | ||
799 | |||
800 | TaskInventoryItem fakeStoreItem = so.RootPart.Inventory.GetInventoryItem(fakeStoreNotecardName); | ||
801 | Assert.That(fakeStoreItem, Is.Null); | ||
802 | } | ||
803 | } | ||
804 | |||
805 | /// <summary> | ||
806 | /// Test for reading json from a notecard | ||
807 | /// </summary> | ||
808 | /// <remarks> | ||
809 | /// TODO: Really needs to test correct receipt of the link_message event. Could do this by directly fetching | ||
810 | /// it via the MockScriptEngine or perhaps by a dummy script instance. | ||
811 | /// </remarks> | ||
812 | [Test] | ||
813 | public void TestJsonReadNotecard() | ||
814 | { | ||
815 | TestHelpers.InMethod(); | ||
816 | // TestHelpers.EnableLogging(); | ||
817 | |||
818 | string notecardName = "nc1"; | ||
819 | |||
820 | SceneObjectGroup so = SceneHelpers.CreateSceneObject(1, TestHelpers.ParseTail(0x1)); | ||
821 | m_scene.AddSceneObject(so); | ||
822 | |||
823 | UUID creatingStoreId = (UUID)InvokeOp("JsonCreateStore", "{ 'Hello':'World' }"); | ||
824 | |||
825 | // Write notecard | ||
826 | InvokeOpOnHost("JsonWriteNotecard", so.UUID, creatingStoreId, "", notecardName); | ||
827 | |||
828 | { | ||
829 | // Read notecard | ||
830 | UUID receivingStoreId = (UUID)InvokeOp("JsonCreateStore", "{}"); | ||
831 | UUID readNotecardRequestId = (UUID)InvokeOpOnHost("JsonReadNotecard", so.UUID, receivingStoreId, "", notecardName); | ||
832 | Assert.That(readNotecardRequestId, Is.Not.EqualTo(UUID.Zero)); | ||
833 | |||
834 | string value = (string)InvokeOp("JsonGetValue", receivingStoreId, "Hello"); | ||
835 | Assert.That(value, Is.EqualTo("World")); | ||
836 | } | ||
837 | |||
838 | { | ||
839 | // Read notecard to new single component path | ||
840 | UUID receivingStoreId = (UUID)InvokeOp("JsonCreateStore", "{}"); | ||
841 | UUID readNotecardRequestId = (UUID)InvokeOpOnHost("JsonReadNotecard", so.UUID, receivingStoreId, "make", notecardName); | ||
842 | Assert.That(readNotecardRequestId, Is.Not.EqualTo(UUID.Zero)); | ||
843 | |||
844 | string value = (string)InvokeOp("JsonGetValue", receivingStoreId, "Hello"); | ||
845 | Assert.That(value, Is.EqualTo("")); | ||
846 | |||
847 | value = (string)InvokeOp("JsonGetValue", receivingStoreId, "make.Hello"); | ||
848 | Assert.That(value, Is.EqualTo("World")); | ||
849 | } | ||
850 | |||
851 | { | ||
852 | // Read notecard to new multi-component path. This should not work. | ||
853 | UUID receivingStoreId = (UUID)InvokeOp("JsonCreateStore", "{}"); | ||
854 | UUID readNotecardRequestId = (UUID)InvokeOpOnHost("JsonReadNotecard", so.UUID, receivingStoreId, "make.it", notecardName); | ||
855 | Assert.That(readNotecardRequestId, Is.Not.EqualTo(UUID.Zero)); | ||
856 | |||
857 | string value = (string)InvokeOp("JsonGetValue", receivingStoreId, "Hello"); | ||
858 | Assert.That(value, Is.EqualTo("")); | ||
859 | |||
860 | value = (string)InvokeOp("JsonGetValue", receivingStoreId, "make.it.Hello"); | ||
861 | Assert.That(value, Is.EqualTo("")); | ||
862 | } | ||
863 | |||
864 | { | ||
865 | // Read notecard to existing multi-component path. This should work | ||
866 | UUID receivingStoreId = (UUID)InvokeOp("JsonCreateStore", "{ 'make' : { 'it' : 'so' } }"); | ||
867 | UUID readNotecardRequestId = (UUID)InvokeOpOnHost("JsonReadNotecard", so.UUID, receivingStoreId, "make.it", notecardName); | ||
868 | Assert.That(readNotecardRequestId, Is.Not.EqualTo(UUID.Zero)); | ||
869 | |||
870 | string value = (string)InvokeOp("JsonGetValue", receivingStoreId, "Hello"); | ||
871 | Assert.That(value, Is.EqualTo("")); | ||
872 | |||
873 | value = (string)InvokeOp("JsonGetValue", receivingStoreId, "make.it.Hello"); | ||
874 | Assert.That(value, Is.EqualTo("World")); | ||
875 | } | ||
876 | |||
877 | { | ||
878 | // Read notecard to invalid path. This should not work. | ||
879 | UUID receivingStoreId = (UUID)InvokeOp("JsonCreateStore", "{ 'make' : { 'it' : 'so' } }"); | ||
880 | UUID readNotecardRequestId = (UUID)InvokeOpOnHost("JsonReadNotecard", so.UUID, receivingStoreId, "/", notecardName); | ||
881 | Assert.That(readNotecardRequestId, Is.Not.EqualTo(UUID.Zero)); | ||
882 | |||
883 | string value = (string)InvokeOp("JsonGetValue", receivingStoreId, "Hello"); | ||
884 | Assert.That(value, Is.EqualTo("")); | ||
885 | } | ||
886 | |||
887 | { | ||
888 | // Try read notecard to fake store. | ||
889 | UUID fakeStoreId = TestHelpers.ParseTail(0x500); | ||
890 | UUID readNotecardRequestId = (UUID)InvokeOpOnHost("JsonReadNotecard", so.UUID, fakeStoreId, "", notecardName); | ||
891 | Assert.That(readNotecardRequestId, Is.Not.EqualTo(UUID.Zero)); | ||
892 | |||
893 | string value = (string)InvokeOp("JsonGetValue", fakeStoreId, "Hello"); | ||
894 | Assert.That(value, Is.EqualTo("")); | ||
895 | } | ||
896 | } | ||
897 | |||
898 | public object DummyTestMethod(object o1, object o2, object o3, object o4, object o5) { return null; } | ||
899 | } | ||
900 | } | ||