1 //
2 // Copyright (c) 2010-2018 Antmicro
3 // Copyright (c) 2011-2015 Realtime Embedded
4 //
5 // This file is licensed under the MIT License.
6 // Full license text is available in 'licenses/MIT.txt'.
7 //
8 
9 using System;
10 using System.Linq;
11 using Antmicro.Renode.Core;
12 using Antmicro.Renode.Peripherals;
13 using Antmicro.Renode.Peripherals.CPU;
14 using NUnit.Framework;
15 using System.IO;
16 using System.Collections.Generic;
17 using Antmicro.Renode.UnitTests.Mocks;
18 using Antmicro.Migrant;
19 using System.Collections.ObjectModel;
20 using Antmicro.Renode.Peripherals.Memory;
21 
22 namespace Antmicro.Renode.UnitTests
23 {
24     [TestFixture]
25     public class SerializationTests
26     {
27         [SetUp]
SetUp()28         public void SetUp()
29         {
30             ClearStream();
31             serializer = new Serializer();
32         }
33 
34         [TearDown]
TearDown()35         public void TearDown()
36         {
37         }
38 
39         [Test]
ShouldSerializeMemory()40         public void ShouldSerializeMemory()
41         {
42             // preparing some random data
43             const int size = 128 * 1024 * 1024;
44             const int bufCount = 30;
45             const int bufSize = 100 * 1024;
46             var random = EmulationManager.Instance.CurrentEmulation.RandomGenerator;
47             var buffers = new List<Tuple<int, byte[]>>(bufCount);
48             for(var i = 0; i < bufCount; i++)
49             {
50                 var buffer = new byte[bufSize];
51                 random.NextBytes(buffer);
52                 int address;
53                 do
54                 {
55                     address = random.Next(size - bufSize);
56                 }
57                 while(buffers.Any(x => address >= (x.Item1 - bufSize) && address <= (x.Item1 + bufSize)));
58                 buffers.Add(new Tuple<int, byte[]>(address, buffer));
59             }
60 
61             using(var memory = new MappedMemory(null, size))
62             {
63                 foreach(var buf in buffers)
64                 {
65                     memory.WriteBytes(buf.Item1, buf.Item2);
66                 }
67                 serializer.Serialize(memory, stream);
68             }
69 
70             RewindStream();
71             using(var memory = serializer.Deserialize<MappedMemory>(stream))
72             {
73                 foreach(var buf in buffers)
74                 {
75                     var bufCopy = memory.ReadBytes(buf.Item1, bufSize);
76                     CollectionAssert.AreEqual(bufCopy, buf.Item2);
77                 }
78             }
79         }
80 
81         [Test]
ShouldSerializeAllCpus([Range(1, 4)] int cpuCount)82         public void ShouldSerializeAllCpus([Range(1, 4)] int cpuCount)
83         {
84             var machine = new Machine();
85             var sysbus = machine.SystemBus;
86             for(var i = 0; i < cpuCount; i++)
87             {
88                 sysbus.Register(new MockCPU(machine), new CPURegistrationPoint());
89             }
90             machine = Serializer.DeepClone(machine);
91             sysbus = machine.SystemBus;
92             var cpus = sysbus.GetCPUs();
93             Assert.AreEqual(cpuCount, cpus.Count());
94         }
95 
96         [Test]
ShouldRememberCpuNames()97         public void ShouldRememberCpuNames()
98         {
99             var names = new[] { "Xavier", "Alice", "Bob" };
100             var machine = new Machine();
101             foreach(var name in names)
102             {
103                 var cpu = new MockCPU(machine) { Placeholder = name };
104                 machine.SystemBus.Register(cpu, new CPURegistrationPoint());
105                 machine.SetLocalName(cpu, name);
106             }
107             machine = Serializer.DeepClone(machine);
108             var cpus = machine.SystemBus.GetCPUs();
109             CollectionAssert.AreEquivalent(names, cpus.Select(x => machine.GetLocalName(x)));
110             foreach(var cpu in cpus.Cast<MockCPU>())
111             {
112                 Assert.AreEqual(cpu.Placeholder, machine.GetLocalName(cpu));
113             }
114         }
115 
116         [Test]
ShouldSerializeGPIOs()117         public void ShouldSerializeGPIOs()
118         {
119             var mocks = new GPIOMock[4];
120             mocks[0] = new GPIOMock { Id = 1 };
121             mocks[1] = new GPIOMock { Id = 2 };
122             mocks[2] = new GPIOMock { Id = 3 };
123             mocks[3] = new GPIOMock { Id = 4 };
124 
125             mocks[0].Connections[0].Connect(mocks[1], 5);
126             mocks[0].Connections[0].Connect(mocks[3], 7);
127             mocks[1].Connections[1].Connect(mocks[2], 0);
128             mocks[2].Connections[2].Connect(mocks[1], 6);
129             mocks[0].GPIOSet(0, true);
130             mocks[2].GPIOSet(1, true);
131             mocks[2].GPIOSet(2, true);
132 
133             var devs = Serializer.DeepClone(mocks).ToList();
134             Assert.AreEqual(4, devs.Count);
135             var mock1 = devs.First(x => x.Id == 1);
136             var mock2 = devs.First(x => x.Id == 2);
137             var mock3 = devs.First(x => x.Id == 3);
138             var mock4 = devs.First(x => x.Id == 4);
139 
140             // checking connections
141             var conn1 = mock1.Connections[0].Endpoints;
142             Assert.AreEqual(5, conn1[0].Number);
143             Assert.AreEqual(7, conn1[1].Number);
144             Assert.AreEqual(mock2, conn1[0].Receiver);
145             Assert.AreEqual(mock4, conn1[1].Receiver);
146             var conn2 = mock2.Connections[1].Endpoints;
147             Assert.AreEqual(0, conn2[0].Number);
148             Assert.AreEqual(mock3, conn2[0].Receiver);
149             var conn3 = mock3.Connections[2].Endpoints;
150             Assert.AreEqual(6, conn3[0].Number);
151             Assert.AreEqual(mock2, conn3[0].Receiver);
152 
153             // checking signaled state
154             Assert.IsTrue(mock2.HasSignaled(5), "Mock 2:5 is not signaled!");
155             Assert.IsTrue(mock2.HasSignaled(6), "Mock 2:6 is not signaled!");
156             Assert.IsFalse(mock3.HasSignaled(0), "Mock 3:0 is signaled!");
157 
158             // now we connect sth to signaled mock3:1 and what happens?
159             mock3.Connections[1].Connect(mock1, 9);
160             Assert.IsTrue(mock1.HasSignaled(9), "Mock 1:9 is not signaled!");
161         }
162 
RewindStream()163         private void RewindStream()
164         {
165             var buffer = stream.GetBuffer();
166             stream = new MemoryStream(buffer, 0, (int)stream.Length);
167         }
168 
ClearStream()169         private void ClearStream()
170         {
171             stream = new MemoryStream();
172         }
173 
174         private MemoryStream stream;
175         private Serializer serializer;
176 
177     }
178 
179     public class GPIOMock : IGPIOReceiver, INumberedGPIOOutput
180     {
GPIOMock()181         public GPIOMock()
182         {
183             var innerConnections = new Dictionary<int, IGPIO>();
184             for(var i = 0; i < 10; i++)
185             {
186                 innerConnections[i] = new GPIO();
187             }
188             Connections = new ReadOnlyDictionary<int, IGPIO>(innerConnections);
189         }
190 
Reset()191         public void Reset()
192         {
193         }
194 
195         public int Id { get; set; }
196 
GPIOSet(int number, bool value)197         public void GPIOSet(int number, bool value)
198         {
199             Connections[number].Set(value);
200         }
201 
HasSignaled(int number)202         public bool HasSignaled(int number)
203         {
204             return activeIns.Contains(number);
205         }
206 
ToString()207         public override string ToString()
208         {
209             return string.Format("[GPIOMock: Id={0}]", Id);
210         }
211 
OnGPIO(int number, bool value)212         public void OnGPIO(int number, bool value)
213         {
214             if(activeIns == null)
215             {
216                 activeIns = new HashSet<int>();
217             }
218             if(value)
219             {
220                 activeIns.Add(number);
221             }
222             else
223             {
224                 activeIns.Remove(number);
225             }
226         }
227 
228         private HashSet<int> activeIns;
229 
230         public IReadOnlyDictionary<int, IGPIO> Connections { get; private set; }
231     }
232 }
233 
234