blob: b09119cb54ec480b25a2d623020d5d0a19c31bca [file] [log] [blame]
Austin Schuhe89fa2d2019-08-14 20:24:23 -07001/*
2 * Copyright 2014 Google Inc. All rights reserved.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17using System.IO;
18using System.Text;
19using MyGame.Example;
20
21namespace FlatBuffers.Test
22{
23 [FlatBuffersTestClass]
24 public class FlatBuffersExampleTests
25 {
26 public void RunTests()
27 {
28 CanCreateNewFlatBufferFromScratch();
29 CanReadCppGeneratedWireFile();
30 TestEnums();
31 }
32
33 [FlatBuffersTestMethod]
34 public void CanCreateNewFlatBufferFromScratch()
35 {
36 CanCreateNewFlatBufferFromScratch(true);
37 CanCreateNewFlatBufferFromScratch(false);
38 }
39
40 private void CanCreateNewFlatBufferFromScratch(bool sizePrefix)
41 {
42 // Second, let's create a FlatBuffer from scratch in C#, and test it also.
43 // We use an initial size of 1 to exercise the reallocation algorithm,
44 // normally a size larger than the typical FlatBuffer you generate would be
45 // better for performance.
46 var fbb = new FlatBufferBuilder(1);
47
48 StringOffset[] names = { fbb.CreateString("Frodo"), fbb.CreateString("Barney"), fbb.CreateString("Wilma") };
49 Offset<Monster>[] off = new Offset<Monster>[3];
50 Monster.StartMonster(fbb);
51 Monster.AddName(fbb, names[0]);
52 off[0] = Monster.EndMonster(fbb);
53 Monster.StartMonster(fbb);
54 Monster.AddName(fbb, names[1]);
55 off[1] = Monster.EndMonster(fbb);
56 Monster.StartMonster(fbb);
57 Monster.AddName(fbb, names[2]);
58 off[2] = Monster.EndMonster(fbb);
59 var sortMons = Monster.CreateSortedVectorOfMonster(fbb, off);
60
61 // We set up the same values as monsterdata.json:
62
63 var str = fbb.CreateString("MyMonster");
64 var test1 = fbb.CreateString("test1");
65 var test2 = fbb.CreateString("test2");
66
67
68 Monster.StartInventoryVector(fbb, 5);
69 for (int i = 4; i >= 0; i--)
70 {
71 fbb.AddByte((byte)i);
72 }
73 var inv = fbb.EndVector();
74
75 var fred = fbb.CreateString("Fred");
76 Monster.StartMonster(fbb);
77 Monster.AddName(fbb, fred);
78 var mon2 = Monster.EndMonster(fbb);
79
80 Monster.StartTest4Vector(fbb, 2);
81 MyGame.Example.Test.CreateTest(fbb, (short)10, (sbyte)20);
82 MyGame.Example.Test.CreateTest(fbb, (short)30, (sbyte)40);
83 var test4 = fbb.EndVector();
84
85 Monster.StartTestarrayofstringVector(fbb, 2);
86 fbb.AddOffset(test2.Value);
87 fbb.AddOffset(test1.Value);
88 var testArrayOfString = fbb.EndVector();
89
90 Monster.StartMonster(fbb);
91 Monster.AddPos(fbb, Vec3.CreateVec3(fbb, 1.0f, 2.0f, 3.0f, 3.0,
92 Color.Green, (short)5, (sbyte)6));
93 Monster.AddHp(fbb, (short)80);
94 Monster.AddName(fbb, str);
95 Monster.AddInventory(fbb, inv);
96 Monster.AddTestType(fbb, Any.Monster);
97 Monster.AddTest(fbb, mon2.Value);
98 Monster.AddTest4(fbb, test4);
99 Monster.AddTestarrayofstring(fbb, testArrayOfString);
100 Monster.AddTestbool(fbb, true);
101 Monster.AddTestarrayoftables(fbb, sortMons);
102 var mon = Monster.EndMonster(fbb);
103
104 if (sizePrefix)
105 {
106 Monster.FinishSizePrefixedMonsterBuffer(fbb, mon);
107 }
108 else
109 {
110 Monster.FinishMonsterBuffer(fbb, mon);
111 }
112
113 // Dump to output directory so we can inspect later, if needed
114#if ENABLE_SPAN_T
115 var data = fbb.DataBuffer.ToSizedArray();
116 string filename = @"Resources/monsterdata_cstest" + (sizePrefix ? "_sp" : "") + ".mon";
117 File.WriteAllBytes(filename, data);
118#else
119 using (var ms = fbb.DataBuffer.ToMemoryStream(fbb.DataBuffer.Position, fbb.Offset))
120 {
121 var data = ms.ToArray();
122 string filename = @"Resources/monsterdata_cstest" + (sizePrefix ? "_sp" : "") + ".mon";
123 File.WriteAllBytes(filename, data);
124 }
125#endif
126
127 // Remove the size prefix if necessary for further testing
128 ByteBuffer dataBuffer = fbb.DataBuffer;
129 if (sizePrefix)
130 {
131 Assert.AreEqual(ByteBufferUtil.GetSizePrefix(dataBuffer) + FlatBufferConstants.SizePrefixLength,
132 dataBuffer.Length - dataBuffer.Position);
133 dataBuffer = ByteBufferUtil.RemoveSizePrefix(dataBuffer);
134 }
135
136 // Now assert the buffer
137 TestBuffer(dataBuffer);
138
139 //Attempt to mutate Monster fields and check whether the buffer has been mutated properly
140 // revert to original values after testing
141 Monster monster = Monster.GetRootAsMonster(dataBuffer);
142
143
144 // mana is optional and does not exist in the buffer so the mutation should fail
145 // the mana field should retain its default value
146 Assert.AreEqual(monster.MutateMana((short)10), false);
147 Assert.AreEqual(monster.Mana, (short)150);
148
149 // Accessing a vector of sorted by the key tables
150 Assert.AreEqual(monster.Testarrayoftables(0).Value.Name, "Barney");
151 Assert.AreEqual(monster.Testarrayoftables(1).Value.Name, "Frodo");
152 Assert.AreEqual(monster.Testarrayoftables(2).Value.Name, "Wilma");
153
154 // Example of searching for a table by the key
155 Assert.IsTrue(monster.TestarrayoftablesByKey("Frodo") != null);
156 Assert.IsTrue(monster.TestarrayoftablesByKey("Barney") != null);
157 Assert.IsTrue(monster.TestarrayoftablesByKey("Wilma") != null);
158
159 // testType is an existing field and mutating it should succeed
160 Assert.AreEqual(monster.TestType, Any.Monster);
161 Assert.AreEqual(monster.MutateTestType(Any.NONE), true);
162 Assert.AreEqual(monster.TestType, Any.NONE);
163 Assert.AreEqual(monster.MutateTestType(Any.Monster), true);
164 Assert.AreEqual(monster.TestType, Any.Monster);
165
166 //mutate the inventory vector
167 Assert.AreEqual(monster.MutateInventory(0, 1), true);
168 Assert.AreEqual(monster.MutateInventory(1, 2), true);
169 Assert.AreEqual(monster.MutateInventory(2, 3), true);
170 Assert.AreEqual(monster.MutateInventory(3, 4), true);
171 Assert.AreEqual(monster.MutateInventory(4, 5), true);
172
173 for (int i = 0; i < monster.InventoryLength; i++)
174 {
175 Assert.AreEqual(monster.Inventory(i), i + 1);
176 }
177
178 //reverse mutation
179 Assert.AreEqual(monster.MutateInventory(0, 0), true);
180 Assert.AreEqual(monster.MutateInventory(1, 1), true);
181 Assert.AreEqual(monster.MutateInventory(2, 2), true);
182 Assert.AreEqual(monster.MutateInventory(3, 3), true);
183 Assert.AreEqual(monster.MutateInventory(4, 4), true);
184
185 // get a struct field and edit one of its fields
186 Vec3 pos = (Vec3)monster.Pos;
187 Assert.AreEqual(pos.X, 1.0f);
188 pos.MutateX(55.0f);
189 Assert.AreEqual(pos.X, 55.0f);
190 pos.MutateX(1.0f);
191 Assert.AreEqual(pos.X, 1.0f);
192
193 TestBuffer(dataBuffer);
194 }
195
196 private void TestBuffer(ByteBuffer bb)
197 {
198 Monster monster = Monster.GetRootAsMonster(bb);
199
200 Assert.AreEqual(80, monster.Hp);
201 Assert.AreEqual(150, monster.Mana);
202 Assert.AreEqual("MyMonster", monster.Name);
203
204 var pos = monster.Pos.Value;
205 Assert.AreEqual(1.0f, pos.X);
206 Assert.AreEqual(2.0f, pos.Y);
207 Assert.AreEqual(3.0f, pos.Z);
208
209 Assert.AreEqual(3.0f, pos.Test1);
210 Assert.AreEqual(Color.Green, pos.Test2);
211 var t = (MyGame.Example.Test)pos.Test3;
212 Assert.AreEqual((short)5, t.A);
213 Assert.AreEqual((sbyte)6, t.B);
214
215 Assert.AreEqual(Any.Monster, monster.TestType);
216
217 var monster2 = monster.Test<Monster>().Value;
218 Assert.AreEqual("Fred", monster2.Name);
219
220
221 Assert.AreEqual(5, monster.InventoryLength);
222 var invsum = 0;
223 for (var i = 0; i < monster.InventoryLength; i++)
224 {
225 invsum += monster.Inventory(i);
226 }
227 Assert.AreEqual(10, invsum);
228
229 // Get the inventory as an array and subtract the
230 // sum to get it back to 0
231 var inventoryArray = monster.GetInventoryArray();
232 Assert.AreEqual(5, inventoryArray.Length);
233 foreach(var inv in inventoryArray)
234 {
235 invsum -= inv;
236 }
237 Assert.AreEqual(0, invsum);
238
239 var test0 = monster.Test4(0).Value;
240 var test1 = monster.Test4(1).Value;
241 Assert.AreEqual(2, monster.Test4Length);
242
243 Assert.AreEqual(100, test0.A + test0.B + test1.A + test1.B);
244
245 Assert.AreEqual(2, monster.TestarrayofstringLength);
246 Assert.AreEqual("test1", monster.Testarrayofstring(0));
247 Assert.AreEqual("test2", monster.Testarrayofstring(1));
248
249 Assert.AreEqual(true, monster.Testbool);
250
251#if ENABLE_SPAN_T
252 var nameBytes = monster.GetNameBytes();
253 Assert.AreEqual("MyMonster", Encoding.UTF8.GetString(nameBytes.ToArray(), 0, nameBytes.Length));
254
255 if (0 == monster.TestarrayofboolsLength)
256 {
257 Assert.IsFalse(monster.GetTestarrayofboolsBytes().Length != 0);
258 }
259 else
260 {
261 Assert.IsTrue(monster.GetTestarrayofboolsBytes().Length != 0);
262 }
263#else
264 var nameBytes = monster.GetNameBytes().Value;
265 Assert.AreEqual("MyMonster", Encoding.UTF8.GetString(nameBytes.Array, nameBytes.Offset, nameBytes.Count));
266
267 if (0 == monster.TestarrayofboolsLength)
268 {
269 Assert.IsFalse(monster.GetTestarrayofboolsBytes().HasValue);
270 }
271 else
272 {
273 Assert.IsTrue(monster.GetTestarrayofboolsBytes().HasValue);
274 }
275#endif
276 }
277
278 [FlatBuffersTestMethod]
279 public void CanReadCppGeneratedWireFile()
280 {
281 var data = File.ReadAllBytes(@"Resources/monsterdata_test.mon");
282 var bb = new ByteBuffer(data);
283 TestBuffer(bb);
284 }
285
286 [FlatBuffersTestMethod]
287 public void TestEnums()
288 {
289 Assert.AreEqual("Red", Color.Red.ToString());
290 Assert.AreEqual("Blue", Color.Blue.ToString());
291 Assert.AreEqual("NONE", Any.NONE.ToString());
292 Assert.AreEqual("Monster", Any.Monster.ToString());
293 }
294
295 [FlatBuffersTestMethod]
296 public void TestNestedFlatBuffer()
297 {
298 const string nestedMonsterName = "NestedMonsterName";
299 const short nestedMonsterHp = 600;
300 const short nestedMonsterMana = 1024;
301 // Create nested buffer as a Monster type
302 var fbb1 = new FlatBufferBuilder(16);
303 var str1 = fbb1.CreateString(nestedMonsterName);
304 Monster.StartMonster(fbb1);
305 Monster.AddName(fbb1, str1);
306 Monster.AddHp(fbb1, nestedMonsterHp);
307 Monster.AddMana(fbb1, nestedMonsterMana);
308 var monster1 = Monster.EndMonster(fbb1);
309 Monster.FinishMonsterBuffer(fbb1, monster1);
310 var fbb1Bytes = fbb1.SizedByteArray();
311 fbb1 = null;
312
313 // Create a Monster which has the first buffer as a nested buffer
314 var fbb2 = new FlatBufferBuilder(16);
315 var str2 = fbb2.CreateString("My Monster");
316 var nestedBuffer = Monster.CreateTestnestedflatbufferVector(fbb2, fbb1Bytes);
317 Monster.StartMonster(fbb2);
318 Monster.AddName(fbb2, str2);
319 Monster.AddHp(fbb2, 50);
320 Monster.AddMana(fbb2, 32);
321 Monster.AddTestnestedflatbuffer(fbb2, nestedBuffer);
322 var monster = Monster.EndMonster(fbb2);
323 Monster.FinishMonsterBuffer(fbb2, monster);
324
325 // Now test the data extracted from the nested buffer
326 var mons = Monster.GetRootAsMonster(fbb2.DataBuffer);
327 var nestedMonster = mons.GetTestnestedflatbufferAsMonster().Value;
328
329 Assert.AreEqual(nestedMonsterMana, nestedMonster.Mana);
330 Assert.AreEqual(nestedMonsterHp, nestedMonster.Hp);
331 Assert.AreEqual(nestedMonsterName, nestedMonster.Name);
332 }
333
334 [FlatBuffersTestMethod]
335 public void TestFixedLenghtArrays()
336 {
337 FlatBufferBuilder builder = new FlatBufferBuilder(100);
338
339 float a;
340 int[] b = new int[15];
341 sbyte c;
342 int[,] d_a = new int[2, 2];
343 TestEnum[] d_b = new TestEnum[2];
344 TestEnum[,] d_c = new TestEnum[2, 2];
345
346 a = 0.5f;
347 for (int i = 0; i < 15; i++) b[i] = i;
348 c = 1;
349 d_a[0, 0] = 1;
350 d_a[0, 1] = 2;
351 d_a[1, 0] = 3;
352 d_a[1, 1] = 4;
353 d_b[0] = TestEnum.B;
354 d_b[1] = TestEnum.C;
355 d_c[0, 0] = TestEnum.A;
356 d_c[0, 1] = TestEnum.B;
357 d_c[1, 0] = TestEnum.C;
358 d_c[1, 1] = TestEnum.B;
359
360 Offset<ArrayStruct> arrayOffset = ArrayStruct.CreateArrayStruct(
361 builder, a, b, c, d_a, d_b, d_c);
362
363 // Create a table with the ArrayStruct.
364 ArrayTable.StartArrayTable(builder);
365 ArrayTable.AddA(builder, arrayOffset);
366 Offset<ArrayTable> tableOffset = ArrayTable.EndArrayTable(builder);
367
368 ArrayTable.FinishArrayTableBuffer(builder, tableOffset);
369
370 ArrayTable table = ArrayTable.GetRootAsArrayTable(builder.DataBuffer);
371
372 Assert.AreEqual(table.A?.A, 0.5f);
373 for (int i = 0; i < 15; i++) Assert.AreEqual(table.A?.B(i), i);
374 Assert.AreEqual(table.A?.C, (sbyte)1);
375 Assert.AreEqual(table.A?.D(0).A(0), 1);
376 Assert.AreEqual(table.A?.D(0).A(1), 2);
377 Assert.AreEqual(table.A?.D(1).A(0), 3);
378 Assert.AreEqual(table.A?.D(1).A(1), 4);
379 Assert.AreEqual(table.A?.D(0).B, TestEnum.B);
380 Assert.AreEqual(table.A?.D(1).B, TestEnum.C);
381 Assert.AreEqual(table.A?.D(0).C(0), TestEnum.A);
382 Assert.AreEqual(table.A?.D(0).C(1), TestEnum.B);
383 Assert.AreEqual(table.A?.D(1).C(0), TestEnum.C);
384 Assert.AreEqual(table.A?.D(1).C(1), TestEnum.B);
385 }
386 }
387}