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