You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

329 lines
6.5 KiB

  1. // go-qrcode
  2. // Copyright 2014 Tom Harwood
  3. package qrcode
  4. import (
  5. "fmt"
  6. "reflect"
  7. "testing"
  8. bitset "github.com/skip2/go-qrcode/bitset"
  9. )
  10. func TestClassifyDataMode(t *testing.T) {
  11. type Test struct {
  12. }
  13. tests := []struct {
  14. data []byte
  15. actual []segment
  16. }{
  17. {
  18. []byte{0x30},
  19. []segment{
  20. {
  21. dataModeNumeric,
  22. []byte{0x30},
  23. },
  24. },
  25. },
  26. {
  27. []byte{0x30, 0x41, 0x42, 0x43, 0x20, 0x00, 0xf0, 0xf1, 0xf2, 0x31},
  28. []segment{
  29. {
  30. dataModeNumeric,
  31. []byte{0x30},
  32. },
  33. {
  34. dataModeAlphanumeric,
  35. []byte{0x41, 0x42, 0x43, 0x20},
  36. },
  37. {
  38. dataModeByte,
  39. []byte{0x00, 0xf0, 0xf1, 0xf2},
  40. },
  41. {
  42. dataModeNumeric,
  43. []byte{0x31},
  44. },
  45. },
  46. },
  47. }
  48. for _, test := range tests {
  49. encoder := newDataEncoder(dataEncoderType1To9)
  50. encoder.encode(test.data)
  51. if !reflect.DeepEqual(test.actual, encoder.actual) {
  52. t.Errorf("Got %v, expected %v", encoder.actual, test.actual)
  53. }
  54. }
  55. }
  56. func TestByteModeLengthCalculations(t *testing.T) {
  57. tests := []struct {
  58. dataEncoderType dataEncoderType
  59. dataMode dataMode
  60. numSymbols int
  61. expectedLength int
  62. }{}
  63. for i, test := range tests {
  64. encoder := newDataEncoder(test.dataEncoderType)
  65. var resultLength int
  66. resultLength, err := encoder.encodedLength(test.dataMode, test.numSymbols)
  67. if test.expectedLength == -1 {
  68. if err == nil {
  69. t.Errorf("Test %d: got length %d, expected error", i, resultLength)
  70. }
  71. } else if resultLength != test.expectedLength {
  72. t.Errorf("Test %d: got length %d, expected length %d", i, resultLength,
  73. test.expectedLength)
  74. }
  75. }
  76. }
  77. func TestSingleModeEncodings(t *testing.T) {
  78. tests := []struct {
  79. dataEncoderType dataEncoderType
  80. dataMode dataMode
  81. data string
  82. expected *bitset.Bitset
  83. }{
  84. {
  85. dataEncoderType1To9,
  86. dataModeNumeric,
  87. "01234567",
  88. bitset.NewFromBase2String("0001 0000001000 0000001100 0101011001 1000011"),
  89. },
  90. {
  91. dataEncoderType1To9,
  92. dataModeAlphanumeric,
  93. "AC-42",
  94. bitset.NewFromBase2String("0010 000000101 00111001110 11100111001 000010"),
  95. },
  96. {
  97. dataEncoderType1To9,
  98. dataModeByte,
  99. "123",
  100. bitset.NewFromBase2String("0100 00000011 00110001 00110010 00110011"),
  101. },
  102. {
  103. dataEncoderType10To26,
  104. dataModeByte,
  105. "123",
  106. bitset.NewFromBase2String("0100 00000000 00000011 00110001 00110010 00110011"),
  107. },
  108. {
  109. dataEncoderType27To40,
  110. dataModeByte,
  111. "123",
  112. bitset.NewFromBase2String("0100 00000000 00000011 00110001 00110010 00110011"),
  113. },
  114. }
  115. for _, test := range tests {
  116. encoder := newDataEncoder(test.dataEncoderType)
  117. encoded := bitset.New()
  118. encoder.encodeDataRaw([]byte(test.data), test.dataMode, encoded)
  119. if !test.expected.Equals(encoded) {
  120. t.Errorf("For %s got %s, expected %s", test.data, encoded.String(),
  121. test.expected.String())
  122. }
  123. }
  124. }
  125. type testModeSegment struct {
  126. dataMode dataMode
  127. numChars int
  128. }
  129. func TestOptimiseEncoding(t *testing.T) {
  130. tests := []struct {
  131. dataEncoderType dataEncoderType
  132. actual []testModeSegment
  133. optimised []testModeSegment
  134. }{
  135. // Coalescing multiple segments.
  136. {
  137. dataEncoderType1To9,
  138. []testModeSegment{
  139. {dataModeAlphanumeric, 1}, // length = 4 + 9 + 6 = 19 bits
  140. {dataModeNumeric, 1}, // length = 4 + 10 + 4 = 18 bits
  141. {dataModeAlphanumeric, 1}, // 19 bits.
  142. {dataModeNumeric, 1}, // 18 bits.
  143. {dataModeAlphanumeric, 1}, // 19 bits.
  144. // total = 93 bits.
  145. },
  146. []testModeSegment{
  147. {dataModeAlphanumeric, 5}, // length = 4 + 9 + 22 + 6 = 41.
  148. },
  149. },
  150. // Coalesing not necessary.
  151. {
  152. dataEncoderType1To9,
  153. []testModeSegment{
  154. {dataModeAlphanumeric, 1},
  155. {dataModeNumeric, 20},
  156. },
  157. []testModeSegment{
  158. {dataModeAlphanumeric, 1},
  159. {dataModeNumeric, 20},
  160. },
  161. },
  162. // Switch to more general dataMode.
  163. {
  164. dataEncoderType1To9,
  165. []testModeSegment{
  166. {dataModeAlphanumeric, 1},
  167. {dataModeByte, 1},
  168. {dataModeNumeric, 1},
  169. },
  170. []testModeSegment{
  171. {dataModeAlphanumeric, 1},
  172. {dataModeByte, 2},
  173. },
  174. },
  175. // https://www.google.com/123
  176. // BBBBBAAABBBABBBBBBABBBANNN
  177. {
  178. dataEncoderType1To9,
  179. []testModeSegment{
  180. {dataModeByte, 5},
  181. {dataModeAlphanumeric, 3},
  182. {dataModeByte, 3},
  183. {dataModeAlphanumeric, 1},
  184. {dataModeByte, 6},
  185. {dataModeAlphanumeric, 1},
  186. {dataModeAlphanumeric, 4},
  187. {dataModeNumeric, 3},
  188. },
  189. []testModeSegment{
  190. {dataModeByte, 23},
  191. {dataModeNumeric, 3},
  192. },
  193. },
  194. // HTTPS://WWW.GOOGLE.COM/123
  195. // AAAAAAAAAAAAAAAAAAAAAAANNN
  196. {
  197. dataEncoderType1To9,
  198. []testModeSegment{
  199. {dataModeAlphanumeric, 23},
  200. {dataModeNumeric, 3},
  201. },
  202. []testModeSegment{
  203. {dataModeAlphanumeric, 26},
  204. },
  205. },
  206. {
  207. dataEncoderType27To40,
  208. []testModeSegment{
  209. {dataModeByte, 1},
  210. {dataModeNumeric, 1},
  211. {dataModeByte, 1},
  212. {dataModeNumeric, 1},
  213. {dataModeByte, 1},
  214. {dataModeNumeric, 1},
  215. {dataModeByte, 1},
  216. {dataModeNumeric, 1},
  217. },
  218. []testModeSegment{
  219. {dataModeByte, 8},
  220. },
  221. },
  222. }
  223. for _, test := range tests {
  224. numTotalChars := 0
  225. for _, v := range test.actual {
  226. numTotalChars += v.numChars
  227. }
  228. data := make([]byte, numTotalChars)
  229. i := 0
  230. for _, v := range test.actual {
  231. for j := 0; j < v.numChars; j++ {
  232. switch v.dataMode {
  233. case dataModeNumeric:
  234. data[i] = '1'
  235. case dataModeAlphanumeric:
  236. data[i] = 'A'
  237. case dataModeByte:
  238. data[i] = '#'
  239. default:
  240. t.Fatal("Unrecognised data mode")
  241. }
  242. i++
  243. }
  244. }
  245. encoder := newDataEncoder(test.dataEncoderType)
  246. _, err := encoder.encode(data)
  247. if err != nil {
  248. t.Errorf("Got %s, expected valid encoding", err.Error())
  249. } else {
  250. ok := true
  251. if len(encoder.optimised) != len(test.optimised) {
  252. ok = false
  253. } else {
  254. for i, s := range test.optimised {
  255. if encoder.optimised[i].dataMode != s.dataMode ||
  256. len(encoder.optimised[i].data) != s.numChars {
  257. ok = false
  258. break
  259. }
  260. }
  261. }
  262. if !ok {
  263. t.Errorf("got %s, expected %s", segmentsString(encoder.optimised),
  264. testModeSegmentsString(test.optimised))
  265. }
  266. }
  267. }
  268. }
  269. func testModeSegmentsString(segments []testModeSegment) string {
  270. result := "["
  271. for i, segment := range segments {
  272. if i > 0 {
  273. result += ", "
  274. }
  275. result += fmt.Sprintf("%d*%s", segment.numChars,
  276. dataModeString(segment.dataMode))
  277. }
  278. result += "]"
  279. return result
  280. }
  281. func segmentsString(segments []segment) string {
  282. result := "["
  283. for i, segment := range segments {
  284. if i > 0 {
  285. result += ", "
  286. }
  287. result += fmt.Sprintf("%d*%s", len(segment.data),
  288. dataModeString(segment.dataMode))
  289. }
  290. result += "]"
  291. return result
  292. }