1 /*
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 
17 using System.IO;
18 using System.Text;
19 using MyGame.Example;
20 
21 namespace FlatBuffers.Test
22 {
23     [FlatBuffersTestClass]
24     public class FlatBuffersExampleTests
25     {
RunTests()26         public void RunTests()
27         {
28             CanCreateNewFlatBufferFromScratch();
29             CanReadCppGeneratedWireFile();
30             TestEnums();
31         }
32 
33         [FlatBuffersTestMethod]
CanCreateNewFlatBufferFromScratch()34         public void CanCreateNewFlatBufferFromScratch()
35         {
36             // Second, let's create a FlatBuffer from scratch in C#, and test it also.
37             // We use an initial size of 1 to exercise the reallocation algorithm,
38             // normally a size larger than the typical FlatBuffer you generate would be
39             // better for performance.
40             var fbb = new FlatBufferBuilder(1);
41 
42             StringOffset[] names = { fbb.CreateString("Frodo"), fbb.CreateString("Barney"), fbb.CreateString("Wilma") };
43             Offset<Monster>[] off = new Offset<Monster>[3];
44             Monster.StartMonster(fbb);
45             Monster.AddName(fbb, names[0]);
46             off[0] = Monster.EndMonster(fbb);
47             Monster.StartMonster(fbb);
48             Monster.AddName(fbb, names[1]);
49             off[1] = Monster.EndMonster(fbb);
50             Monster.StartMonster(fbb);
51             Monster.AddName(fbb, names[2]);
52             off[2] = Monster.EndMonster(fbb);
53             var sortMons = Monster.CreateMySortedVectorOfTables(fbb, off);
54 
55             // We set up the same values as monsterdata.json:
56 
57             var str = fbb.CreateString("MyMonster");
58             var test1 = fbb.CreateString("test1");
59             var test2 = fbb.CreateString("test2");
60 
61 
62             Monster.StartInventoryVector(fbb, 5);
63             for (int i = 4; i >= 0; i--)
64             {
65                 fbb.AddByte((byte)i);
66             }
67             var inv = fbb.EndVector();
68 
69             var fred = fbb.CreateString("Fred");
70             Monster.StartMonster(fbb);
71             Monster.AddName(fbb, fred);
72             var mon2 = Monster.EndMonster(fbb);
73 
74             Monster.StartTest4Vector(fbb, 2);
75             MyGame.Example.Test.CreateTest(fbb, (short)10, (sbyte)20);
76             MyGame.Example.Test.CreateTest(fbb, (short)30, (sbyte)40);
77             var test4 = fbb.EndVector();
78 
79             Monster.StartTestarrayofstringVector(fbb, 2);
80             fbb.AddOffset(test2.Value);
81             fbb.AddOffset(test1.Value);
82             var testArrayOfString = fbb.EndVector();
83 
84             Monster.StartMonster(fbb);
85             Monster.AddPos(fbb, Vec3.CreateVec3(fbb, 1.0f, 2.0f, 3.0f, 3.0,
86                                                      Color.Green, (short)5, (sbyte)6));
87             Monster.AddHp(fbb, (short)80);
88             Monster.AddName(fbb, str);
89             Monster.AddInventory(fbb, inv);
90             Monster.AddTestType(fbb, Any.Monster);
91             Monster.AddTest(fbb, mon2.Value);
92             Monster.AddTest4(fbb, test4);
93             Monster.AddTestarrayofstring(fbb, testArrayOfString);
94             Monster.AddTestbool(fbb, false);
95             Monster.AddTestarrayoftables(fbb, sortMons);
96             var mon = Monster.EndMonster(fbb);
97 
98             Monster.FinishMonsterBuffer(fbb, mon);
99 
100 
101             // Dump to output directory so we can inspect later, if needed
102             using (var ms = new MemoryStream(fbb.DataBuffer.Data, fbb.DataBuffer.Position, fbb.Offset))
103             {
104                 var data = ms.ToArray();
105                 File.WriteAllBytes(@"Resources/monsterdata_cstest.mon",data);
106             }
107 
108             // Now assert the buffer
109             TestBuffer(fbb.DataBuffer);
110 
111             //Attempt to mutate Monster fields and check whether the buffer has been mutated properly
112             // revert to original values after testing
113             Monster monster = Monster.GetRootAsMonster(fbb.DataBuffer);
114 
115             // mana is optional and does not exist in the buffer so the mutation should fail
116             // the mana field should retain its default value
117             Assert.AreEqual(monster.MutateMana((short)10), false);
118             Assert.AreEqual(monster.Mana, (short)150);
119 
120             // Accessing a vector of sorted by the key tables
121             Assert.AreEqual(monster.Testarrayoftables(0).Value.Name, "Barney");
122             Assert.AreEqual(monster.Testarrayoftables(1).Value.Name, "Frodo");
123             Assert.AreEqual(monster.Testarrayoftables(2).Value.Name, "Wilma");
124 
125             // Example of searching for a table by the key
126             Assert.IsTrue(Monster.LookupByKey(sortMons, "Frodo", fbb.DataBuffer) != null);
127             Assert.IsTrue(Monster.LookupByKey(sortMons, "Barney", fbb.DataBuffer) != null);
128             Assert.IsTrue(Monster.LookupByKey(sortMons, "Wilma", fbb.DataBuffer)!= null);
129 
130             // testType is an existing field and mutating it should succeed
131             Assert.AreEqual(monster.TestType, Any.Monster);
132             Assert.AreEqual(monster.MutateTestType(Any.NONE), true);
133             Assert.AreEqual(monster.TestType, Any.NONE);
134             Assert.AreEqual(monster.MutateTestType(Any.Monster), true);
135             Assert.AreEqual(monster.TestType, Any.Monster);
136 
137             //mutate the inventory vector
138             Assert.AreEqual(monster.MutateInventory(0, 1), true);
139             Assert.AreEqual(monster.MutateInventory(1, 2), true);
140             Assert.AreEqual(monster.MutateInventory(2, 3), true);
141             Assert.AreEqual(monster.MutateInventory(3, 4), true);
142             Assert.AreEqual(monster.MutateInventory(4, 5), true);
143 
144             for (int i = 0; i < monster.InventoryLength; i++)
145             {
146                 Assert.AreEqual(monster.Inventory(i), i + 1);
147             }
148 
149             //reverse mutation
150             Assert.AreEqual(monster.MutateInventory(0, 0), true);
151             Assert.AreEqual(monster.MutateInventory(1, 1), true);
152             Assert.AreEqual(monster.MutateInventory(2, 2), true);
153             Assert.AreEqual(monster.MutateInventory(3, 3), true);
154             Assert.AreEqual(monster.MutateInventory(4, 4), true);
155 
156             // get a struct field and edit one of its fields
157             Vec3 pos = (Vec3)monster.Pos;
158             Assert.AreEqual(pos.X, 1.0f);
159             pos.MutateX(55.0f);
160             Assert.AreEqual(pos.X, 55.0f);
161             pos.MutateX(1.0f);
162             Assert.AreEqual(pos.X, 1.0f);
163 
164             TestBuffer(fbb.DataBuffer);
165         }
166 
TestBuffer(ByteBuffer bb)167         private void TestBuffer(ByteBuffer bb)
168         {
169             var monster = Monster.GetRootAsMonster(bb);
170 
171             Assert.AreEqual(80, monster.Hp);
172             Assert.AreEqual(150, monster.Mana);
173             Assert.AreEqual("MyMonster", monster.Name);
174 
175             var pos = monster.Pos.Value;
176             Assert.AreEqual(1.0f, pos.X);
177             Assert.AreEqual(2.0f, pos.Y);
178             Assert.AreEqual(3.0f, pos.Z);
179 
180             Assert.AreEqual(3.0f, pos.Test1);
181             Assert.AreEqual(Color.Green, pos.Test2);
182             var t = (MyGame.Example.Test)pos.Test3;
183             Assert.AreEqual((short)5, t.A);
184             Assert.AreEqual((sbyte)6, t.B);
185 
186             Assert.AreEqual(Any.Monster, monster.TestType);
187 
188             var monster2 = monster.Test<Monster>().Value;
189             Assert.AreEqual("Fred", monster2.Name);
190 
191 
192             Assert.AreEqual(5, monster.InventoryLength);
193             var invsum = 0;
194             for (var i = 0; i < monster.InventoryLength; i++)
195             {
196                 invsum += monster.Inventory(i);
197             }
198             Assert.AreEqual(10, invsum);
199 
200             var test0 = monster.Test4(0).Value;
201             var test1 = monster.Test4(1).Value;
202             Assert.AreEqual(2, monster.Test4Length);
203 
204             Assert.AreEqual(100, test0.A + test0.B + test1.A + test1.B);
205 
206             Assert.AreEqual(2, monster.TestarrayofstringLength);
207             Assert.AreEqual("test1", monster.Testarrayofstring(0));
208             Assert.AreEqual("test2", monster.Testarrayofstring(1));
209 
210             Assert.AreEqual(false, monster.Testbool);
211 
212             var nameBytes = monster.GetNameBytes().Value;
213             Assert.AreEqual("MyMonster", Encoding.UTF8.GetString(nameBytes.Array, nameBytes.Offset, nameBytes.Count));
214 
215             if (0 == monster.TestarrayofboolsLength)
216             {
217                 Assert.IsFalse(monster.GetTestarrayofboolsBytes().HasValue);
218             }
219             else
220             {
221                 Assert.IsTrue(monster.GetTestarrayofboolsBytes().HasValue);
222             }
223         }
224 
225         [FlatBuffersTestMethod]
CanReadCppGeneratedWireFile()226         public void CanReadCppGeneratedWireFile()
227         {
228             var data = File.ReadAllBytes(@"Resources/monsterdata_test.mon");
229             var bb = new ByteBuffer(data);
230             TestBuffer(bb);
231         }
232 
233         [FlatBuffersTestMethod]
TestEnums()234         public void TestEnums()
235         {
236             Assert.AreEqual("Red", Color.Red.ToString());
237             Assert.AreEqual("Blue", Color.Blue.ToString());
238             Assert.AreEqual("NONE", Any.NONE.ToString());
239             Assert.AreEqual("Monster", Any.Monster.ToString());
240         }
241 
242         [FlatBuffersTestMethod]
TestNestedFlatBuffer()243         public void TestNestedFlatBuffer()
244         {
245             const string nestedMonsterName = "NestedMonsterName";
246             const short nestedMonsterHp = 600;
247             const short nestedMonsterMana = 1024;
248             // Create nested buffer as a Monster type
249             var fbb1 = new FlatBufferBuilder(16);
250             var str1 = fbb1.CreateString(nestedMonsterName);
251             Monster.StartMonster(fbb1);
252             Monster.AddName(fbb1, str1);
253             Monster.AddHp(fbb1, nestedMonsterHp);
254             Monster.AddMana(fbb1, nestedMonsterMana);
255             var monster1 = Monster.EndMonster(fbb1);
256             Monster.FinishMonsterBuffer(fbb1, monster1);
257             var fbb1Bytes = fbb1.SizedByteArray();
258             fbb1 = null;
259 
260             // Create a Monster which has the first buffer as a nested buffer
261             var fbb2 = new FlatBufferBuilder(16);
262             var str2 = fbb2.CreateString("My Monster");
263             var nestedBuffer = Monster.CreateTestnestedflatbufferVector(fbb2, fbb1Bytes);
264             Monster.StartMonster(fbb2);
265             Monster.AddName(fbb2, str2);
266             Monster.AddHp(fbb2, 50);
267             Monster.AddMana(fbb2, 32);
268             Monster.AddTestnestedflatbuffer(fbb2, nestedBuffer);
269             var monster = Monster.EndMonster(fbb2);
270             Monster.FinishMonsterBuffer(fbb2, monster);
271 
272             // Now test the data extracted from the nested buffer
273             var mons = Monster.GetRootAsMonster(fbb2.DataBuffer);
274             var nestedMonster = mons.GetTestnestedflatbufferAsMonster().Value;
275 
276             Assert.AreEqual(nestedMonsterMana, nestedMonster.Mana);
277             Assert.AreEqual(nestedMonsterHp, nestedMonster.Hp);
278             Assert.AreEqual(nestedMonsterName, nestedMonster.Name);
279         }
280     }
281 }
282