DataExtensionsTests.swift 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358
  1. //
  2. // MAVLinkTests.swift
  3. // MAVLinkTests
  4. //
  5. // Created by Max Odnovolyk on 9/28/16.
  6. // Copyright © 2016 Build Apps. All rights reserved.
  7. //
  8. import Foundation
  9. import XCTest
  10. @testable import MAVLink
  11. class DataExtensionsTests: XCTestCase {
  12. // MARK: - Test number<T: MAVLinkNumber>(at offset: Data.Index, byteOrder: CFByteOrder) throws -> T
  13. func testGetNumberCannotGetTooLargeNumber() {
  14. let data = Data(count: 4)
  15. let test: () throws -> Void = {
  16. let _: Int32 = try data.number(at: 1)
  17. }
  18. XCTAssertThrowsError(try test()) { error in
  19. switch error {
  20. case let ParseError.valueSizeOutOfBounds(offset, size, upperBound) where offset + size > upperBound:
  21. break
  22. default:
  23. XCTFail("Unexpected error thrown")
  24. }
  25. }
  26. }
  27. func testGetNumberDidGetNumberAtOffset() {
  28. let data = Data(bytes: [0x00, 0x00, 0x01, 0x02, 0x03, 0x04])
  29. let expectedNumber: UInt32 = 0x01_02_03_04
  30. let receivedNumber: UInt32 = try! data.number(at: 2, byteOrder: .bigEndian)
  31. XCTAssert(receivedNumber == expectedNumber, "Method should return number value available at specified offset in data")
  32. }
  33. func testGetNumberByteOrderIsSwappedOnLittleEndianSystem() {
  34. let memoryBytes: [UInt8] = [0x04, 0x03, 0x02, 0x01]
  35. let expectedNumber: UInt32 = 0x01_02_03_04
  36. let data = Data(bytes: memoryBytes)
  37. let receivedNumber: UInt32 = try! data.number(at: 0, byteOrder: .littleEndian)
  38. XCTAssert(receivedNumber == expectedNumber, "Method expects swapped bytes in memory on little-endian system (most significant digit byte at the end)")
  39. }
  40. func testGetNumberByteOrderRemainsSameOnBigEndianSystem() {
  41. let memoryBytes: [UInt8] = [0x01, 0x02, 0x03, 0x04]
  42. let expectedNumber: UInt32 = 0x01_02_03_04
  43. let data = Data(bytes: memoryBytes)
  44. let receivedNumber: UInt32 = try! data.number(at: 0, byteOrder: .bigEndian)
  45. XCTAssert(receivedNumber == expectedNumber, "Method expects less significant digit byte at the end of value's memory chunk")
  46. }
  47. // MARK: Test array<T: MAVLinkNumber>(at offset: Data.Index, capacity: Int) throws -> [T]
  48. func testGetArrayCannotAccessBytesOutOfDataUpperBound() {
  49. let data = Data(count: 4)
  50. let test: () throws -> Void = {
  51. let _: [UInt8] = try data.array(at: 1, capacity: 4)
  52. }
  53. XCTAssertThrowsError(try test()) { error in
  54. switch error {
  55. case let ParseError.valueSizeOutOfBounds(offset, size, upperBound) where offset + size > upperBound:
  56. break
  57. default:
  58. XCTFail("Unexpected error thrown")
  59. }
  60. }
  61. }
  62. func testGetArrayDidGetArrayAtOffset() {
  63. let data = Data(bytes: [0x00, 0x00, 0x01, 0x02, 0x03, 0x00])
  64. let expectedArray: [UInt8] = [0x01, 0x02, 0x03]
  65. let receivedArray: [UInt8] = try! data.array(at: 2, capacity: 3)
  66. XCTAssert(receivedArray == expectedArray, "Expect array values at specified offset in data")
  67. }
  68. func testGetArrayDidGetRequestedNumberOfItems() {
  69. let data = Data(count: 4)
  70. let itemsCountToGet = 3
  71. let receivedArray: [UInt8] = try! data.array(at: 1, capacity: itemsCountToGet)
  72. XCTAssert(receivedArray.count == itemsCountToGet, "Expect requested capacity of array to be equal to received array's count")
  73. }
  74. // MARK: Test string(at offset: Data.Index, length: Int) throws -> String
  75. func testGetStringCannotAccessBytesOutOfDataUpperBound() {
  76. let data = Data(count: 4)
  77. XCTAssertThrowsError(try data.string(at: 1, length: 4)) { error in
  78. switch error {
  79. case let ParseError.valueSizeOutOfBounds(offset, size, upperBound) where offset + size > upperBound:
  80. break
  81. default:
  82. XCTFail("Unexpected error thrown")
  83. }
  84. }
  85. }
  86. func testGetStringCannotReadNonASCIISEncodedString() {
  87. // Check that invalidStringEncoding is thrown in case of non ASCII compatible strings.
  88. // It looks like all strings are ASCII compatible for String(bytes: encoding:) method.
  89. }
  90. func testGetStringDidReadASCIIEncodedStringAtSpecifiedOffset() {
  91. let data = Data(bytes: [0x60, 0x61, 0x62, 0x63, 0x64, 0x65]) // "`abcde"
  92. let string = try! data.string(at: 3, length: 3)
  93. XCTAssert(string == "cde", "Expect string at offset 3 (cde)")
  94. }
  95. func testGetStringDidReadEmptyNullTerminatedASCIIEncodedString() {
  96. let data = Data(bytes: [0x00, 0x00, 0x00, 0x00, 0x00, 0x00]) // "\0\0\0\0\0\0"
  97. let string = try! data.string(at: 1, length: 4)
  98. XCTAssert(string == "", "Expect to get empty string from zeroed data bytes")
  99. }
  100. func testGetStringDidReadNullTerminatedASCIIEncodedString() {
  101. let data = Data(bytes: [0x60, 0x61, 0x62, 0x0, 0x64, 0x65]) // "`ab\0de"
  102. let string = try! data.string(at: 1, length: 4)
  103. XCTAssert(string == "ab", "Expect cutted off by null-termination string")
  104. }
  105. func testGetStringDidReadExactlyLengthSizedASCIIEncodedStringWithoutNullTermination() {
  106. let data = Data(bytes: [0x60, 0x61, 0x62, 0x63, 0x64, 0x65]) // "`abcde"
  107. let string = try! data.string(at: 1, length: 3)
  108. XCTAssert(string == "abc", "Expect cutted off by length limit string")
  109. }
  110. // MARK: Test enumeration<T: Enumeration>(at offset: Data.Index) throws -> T where T.RawValue: MAVLinkNumber
  111. func testGetEnumerationCannotInitWithUnknownValue() {
  112. let data = Data(bytes: [UInt8(ADSBAltitudeType.enumEnd)])
  113. let test: () throws -> Void = {
  114. let _: ADSBAltitudeType = try data.enumeration(at: 0)
  115. }
  116. XCTAssertThrowsError(try test()) { error in
  117. switch error {
  118. case ParseEnumError<ADSBAltitudeType>.unknownValue:
  119. break
  120. default:
  121. XCTFail("Unexpected error thrown")
  122. }
  123. }
  124. }
  125. func testGetEnumerationDidGetProperCaseAtOffset() {
  126. let data = Data(bytes: [0x00, 0x00, ADSBAltitudeType.geometric.rawValue])
  127. let adsbAltitudeType: ADSBAltitudeType = try! data.enumeration(at: 2)
  128. XCTAssert(adsbAltitudeType == .geometric, "Expected adsbAltitudeType is .geometric")
  129. }
  130. // MARK: - Test set<T: MAVLinkNumber>(_ number: T, at offset: Data.Index, byteOrder: CFByteOrder) throws -> Void
  131. func testSetNumberCannotSetTooLargeNumber() {
  132. var data = Data(count: 4)
  133. XCTAssertThrowsError(try data.set(Int32(1), at: 1)) { error in
  134. switch error {
  135. case let PackError.valueSizeOutOfBounds(offset, size, upperBound) where offset + size > upperBound:
  136. break
  137. default:
  138. XCTFail("Unexpected error thrown")
  139. }
  140. }
  141. }
  142. func testSetNumberDidSetNumberAtOffset() {
  143. var data = Data(count: 6)
  144. let number: UInt32 = 0x01_02_03_04
  145. let expectedData = Data(bytes: [0x00, 0x00, 0x01, 0x02, 0x03, 0x04])
  146. try! data.set(number, at: 2, byteOrder: .bigEndian)
  147. XCTAssert(data == expectedData, "Method should set number at specified offset in data memory")
  148. }
  149. func testSetNumberByteOrderIsSwappedOnLittleEndianSystem() {
  150. var data = Data(count: 4)
  151. let number: UInt32 = 0x01_02_03_04
  152. let expectedData = Data(bytes: [0x04, 0x03, 0x02, 0x01])
  153. try! data.set(number, at: 0, byteOrder: .littleEndian)
  154. XCTAssert(data == expectedData, "Method should write swapped bytes in memory on little-endian system (most significant digit byte at the end)")
  155. }
  156. func testSetNumberByteOrderRemainsSameOnBigEndianSystem() {
  157. var data = Data(count: 4)
  158. let number: UInt32 = 0x01_02_03_04
  159. let expectedData = Data(bytes: [0x01, 0x02, 0x03, 0x04])
  160. try! data.set(number, at: 0, byteOrder: .bigEndian)
  161. XCTAssert(data == expectedData, "Method should write less significant digit byte at the end of data's memory chunk")
  162. }
  163. // MARK: Test set<T: MAVLinkNumber>(_ array: [T], at offset: Data.Index, capacity: Int) throws
  164. func testSetArrayCannotSetArrayWithLessCapacityThanArrayCount() {
  165. var data = Data(count: 6)
  166. let array = Array<UInt8>(repeating: 0, count: 4)
  167. XCTAssertThrowsError(try data.set(array, at: 0, capacity: 3)) { error in
  168. switch error {
  169. case let PackError.invalidValueLength(offset, providedValueLength, allowedLength) where offset == 0 && providedValueLength > allowedLength:
  170. break
  171. default:
  172. XCTFail("Unexpected error thrown")
  173. }
  174. }
  175. }
  176. func testSetArrayCannotSetValuesOutOfDataUpperBound() {
  177. var data = Data(count: 10)
  178. let array = Array<UInt64>(repeating: 0, count: 2)
  179. XCTAssertThrowsError(try data.set(array, at: 0, capacity: 16)) { error in
  180. switch error {
  181. case let PackError.valueSizeOutOfBounds(offset, size, upperBound) where offset == 0 && offset + size > upperBound:
  182. break
  183. default:
  184. XCTFail("Unexpected error thrown")
  185. }
  186. }
  187. }
  188. func testSetArrayDidSetValuesAtOffset() {
  189. var data = Data(count: 6)
  190. let array: [UInt8] = [0x01, 0x02, 0x03, 0x04]
  191. let expectedData = Data(bytes: [0x00, 0x01, 0x02, 0x03, 0x04, 0x00])
  192. try! data.set(array, at: 1, capacity: 4)
  193. XCTAssert(data == expectedData, "Method should write array values at specified offset")
  194. }
  195. // MARK: Test set(_ string: String, at offset: Data.Index, length: Int) throws
  196. func testSetStringCannotSetNonASCIIString() {
  197. var data = Data(count: 10)
  198. XCTAssertThrowsError(try data.set("💩", at: 0, length: 4)) { error in
  199. switch error {
  200. case let PackError.invalidStringEncoding(offset, string) where offset == 0 && string == "💩":
  201. break
  202. default:
  203. XCTFail("Unexpected error thrown")
  204. }
  205. }
  206. }
  207. func testSetStringCanntSetTooLongString() {
  208. var data = Data(count: 5)
  209. XCTAssertThrowsError(try data.set("abcdef", at: 0, length: 6)) { error in
  210. switch error {
  211. case let PackError.valueSizeOutOfBounds(offset, size, upperBound) where offset == 0 && offset + size > upperBound:
  212. break
  213. default:
  214. XCTFail("Unexpected error thrown")
  215. }
  216. }
  217. }
  218. func testSetStringDidSetNullTerminatedStringAtOffset() {
  219. var data = Data(bytes: Array<UInt8>(repeating: 0xFF, count: 5))
  220. let expectedData = Data(bytes: [0xFF, 0x61, 0x62, 0x63, 0x00])
  221. try! data.set("abc", at: 1, length: 4)
  222. XCTAssert(data == expectedData, "Method should write ASCII string bytes at specified offset with null byte at the end")
  223. }
  224. func testSetStringDidSetEmptyString() {
  225. var data = Data(bytes: Array<UInt8>(repeating: 0xFF, count: 5))
  226. let expectedData = Data(bytes: [0xFF, 0xFF, 0x00, 0xFF, 0xFF])
  227. try! data.set("", at: 2, length: 3)
  228. XCTAssert(data == expectedData, "Method should accept empty string as valid ASCII encoded string and add null termination")
  229. }
  230. // MARK: Test set<T: Enumeration>(_ enumeration: T, at offset: Data.Index) throws
  231. func testSetEnumerationDidSetProperRawValueAtOffset() {
  232. var data = Data(bytes: Array<UInt8>(repeating: 0x00, count: 4))
  233. let expectedData = Data(bytes: [0x00, 0x00, 0x00, MAVVTOLState.fw.rawValue])
  234. try! data.set(MAVVTOLState.fw, at: 3)
  235. XCTAssert(data == expectedData, "Method should set appropriate case raw value at specified offset")
  236. }
  237. // MARK: - Test write-read methods calls return consistent values
  238. func testGetNumberDidGetSameValuePreviouslySetWithSetNumberCall() {
  239. var data = Data(count: 10)
  240. let offset = 1
  241. let number = UInt64(0x01_02_03_04_05_06_07_08)
  242. try! data.set(number, at: offset)
  243. let receivedNumber: UInt64 = try! data.number(at: offset)
  244. XCTAssert(receivedNumber == number)
  245. }
  246. func testGetArrayDidGetSameValuePreviouslySetWithSetArrayCall() {
  247. var data = Data(count: 10)
  248. let offset = 1
  249. let array: [UInt8] = [0x00, 0x01, 0x02, 0x03, 0x04]
  250. try! data.set(array, at: offset, capacity: 5)
  251. let receivedArray: [UInt8] = try! data.array(at: offset, capacity: 5)
  252. XCTAssert(receivedArray == array)
  253. }
  254. func testGetStringDidGetSameValuePreviouslySetWithSetStringCall() {
  255. var data = Data(count: 10)
  256. let offset = 1
  257. let string = "test"
  258. try! data.set(string, at: offset, length: 9)
  259. let receivedString = try! data.string(at: offset, length: 9)
  260. XCTAssert(receivedString == string)
  261. }
  262. func testGetEnumerationDidGetSameValuePreviouslySetWithSetEnumerationCall() {
  263. var data = Data(count: 10)
  264. let offset = 1
  265. let mavvtolState = MAVVTOLState.fw
  266. try! data.set(mavvtolState, at: offset)
  267. let receivedMavvtolState: MAVVTOLState = try! data.enumeration(at: offset)
  268. XCTAssert(receivedMavvtolState == mavvtolState)
  269. }
  270. }