const test = require('tap').test const Version = require('core/version') const VersionCheck = require('core/version-check') const ECLevel = require('core/error-correction-level') const Mode = require('core/mode') const NumericData = require('core/numeric-data') const AlphanumericData = require('core/alphanumeric-data') const KanjiData = require('core/kanji-data') const ByteData = require('core/byte-data') const EC_LEVELS = [ECLevel.L, ECLevel.M, ECLevel.Q, ECLevel.H] const EXPECTED_NUMERIC_CAPACITY = [ [41, 34, 27, 17], [77, 63, 48, 34], [127, 101, 77, 58], [187, 149, 111, 82], [255, 202, 144, 106], [322, 255, 178, 139], [370, 293, 207, 154], [461, 365, 259, 202], [552, 432, 312, 235], [652, 513, 364, 288], [772, 604, 427, 331], [883, 691, 489, 374], [1022, 796, 580, 427], [1101, 871, 621, 468], [1250, 991, 703, 530], [1408, 1082, 775, 602], [1548, 1212, 876, 674], [1725, 1346, 948, 746], [1903, 1500, 1063, 813], [2061, 1600, 1159, 919], [2232, 1708, 1224, 969], [2409, 1872, 1358, 1056], [2620, 2059, 1468, 1108], [2812, 2188, 1588, 1228], [3057, 2395, 1718, 1286], [3283, 2544, 1804, 1425], [3517, 2701, 1933, 1501], [3669, 2857, 2085, 1581], [3909, 3035, 2181, 1677], [4158, 3289, 2358, 1782], [4417, 3486, 2473, 1897], [4686, 3693, 2670, 2022], [4965, 3909, 2805, 2157], [5253, 4134, 2949, 2301], [5529, 4343, 3081, 2361], [5836, 4588, 3244, 2524], [6153, 4775, 3417, 2625], [6479, 5039, 3599, 2735], [6743, 5313, 3791, 2927], [7089, 5596, 3993, 3057] ] const EXPECTED_ALPHANUMERIC_CAPACITY = [ [25, 20, 16, 10], [47, 38, 29, 20], [77, 61, 47, 35], [114, 90, 67, 50], [154, 122, 87, 64], [195, 154, 108, 84], [224, 178, 125, 93], [279, 221, 157, 122], [335, 262, 189, 143], [395, 311, 221, 174], [468, 366, 259, 200], [535, 419, 296, 227], [619, 483, 352, 259], [667, 528, 376, 283], [758, 600, 426, 321], [854, 656, 470, 365], [938, 734, 531, 408], [1046, 816, 574, 452], [1153, 909, 644, 493], [1249, 970, 702, 557], [1352, 1035, 742, 587], [1460, 1134, 823, 640], [1588, 1248, 890, 672], [1704, 1326, 963, 744], [1853, 1451, 1041, 779], [1990, 1542, 1094, 864], [2132, 1637, 1172, 910], [2223, 1732, 1263, 958], [2369, 1839, 1322, 1016], [2520, 1994, 1429, 1080], [2677, 2113, 1499, 1150], [2840, 2238, 1618, 1226], [3009, 2369, 1700, 1307], [3183, 2506, 1787, 1394], [3351, 2632, 1867, 1431], [3537, 2780, 1966, 1530], [3729, 2894, 2071, 1591], [3927, 3054, 2181, 1658], [4087, 3220, 2298, 1774], [4296, 3391, 2420, 1852] ] const EXPECTED_KANJI_CAPACITY = [ [10, 8, 7, 4], [20, 16, 12, 8], [32, 26, 20, 15], [48, 38, 28, 21], [65, 52, 37, 27], [82, 65, 45, 36], [95, 75, 53, 39], [118, 93, 66, 52], [141, 111, 80, 60], [167, 131, 93, 74], [198, 155, 109, 85], [226, 177, 125, 96], [262, 204, 149, 109], [282, 223, 159, 120], [320, 254, 180, 136], [361, 277, 198, 154], [397, 310, 224, 173], [442, 345, 243, 191], [488, 384, 272, 208], [528, 410, 297, 235], [572, 438, 314, 248], [618, 480, 348, 270], [672, 528, 376, 284], [721, 561, 407, 315], [784, 614, 440, 330], [842, 652, 462, 365], [902, 692, 496, 385], [940, 732, 534, 405], [1002, 778, 559, 430], [1066, 843, 604, 457], [1132, 894, 634, 486], [1201, 947, 684, 518], [1273, 1002, 719, 553], [1347, 1060, 756, 590], [1417, 1113, 790, 605], [1496, 1176, 832, 647], [1577, 1224, 876, 673], [1661, 1292, 923, 701], [1729, 1362, 972, 750], [1817, 1435, 1024, 784] ] const EXPECTED_BYTE_CAPACITY = [ [17, 14, 11, 7], [32, 26, 20, 14], [53, 42, 32, 24], [78, 62, 46, 34], [106, 84, 60, 44], [134, 106, 74, 58], [154, 122, 86, 64], [192, 152, 108, 84], [230, 180, 130, 98], [271, 213, 151, 119], [321, 251, 177, 137], [367, 287, 203, 155], [425, 331, 241, 177], [458, 362, 258, 194], [520, 412, 292, 220], [586, 450, 322, 250], [644, 504, 364, 280], [718, 560, 394, 310], [792, 624, 442, 338], [858, 666, 482, 382], [929, 711, 509, 403], [1003, 779, 565, 439], [1091, 857, 611, 461], [1171, 911, 661, 511], [1273, 997, 715, 535], [1367, 1059, 751, 593], [1465, 1125, 805, 625], [1528, 1190, 868, 658], [1628, 1264, 908, 698], [1732, 1370, 982, 742], [1840, 1452, 1030, 790], [1952, 1538, 1112, 842], [2068, 1628, 1168, 898], [2188, 1722, 1228, 958], [2303, 1809, 1283, 983], [2431, 1911, 1351, 1051], [2563, 1989, 1423, 1093], [2699, 2099, 1499, 1139], [2809, 2213, 1579, 1219], [2953, 2331, 1663, 1273] ] const EXPECTED_VERSION_BITS = [ 0x07C94, 0x085BC, 0x09A99, 0x0A4D3, 0x0BBF6, 0x0C762, 0x0D847, 0x0E60D, 0x0F928, 0x10B78, 0x1145D, 0x12A17, 0x13532, 0x149A6, 0x15683, 0x168C9, 0x177EC, 0x18EC4, 0x191E1, 0x1AFAB, 0x1B08E, 0x1CC1A, 0x1D33F, 0x1ED75, 0x1F250, 0x209D5, 0x216F0, 0x228BA, 0x2379F, 0x24B0B, 0x2542E, 0x26A64, 0x27541, 0x28C69 ] test('Version validity', function (t) { t.notOk(VersionCheck.isValid(), 'Should return false if no input') t.notOk(VersionCheck.isValid(''), 'Should return false if version is not a number') t.notOk(VersionCheck.isValid(0), 'Should return false if version is not in range') t.notOk(VersionCheck.isValid(41), 'Should return false if version is not in range') t.end() }) test('Version from value', function (t) { t.equal(Version.from(5), 5, 'Should return correct version from a number') t.equal(Version.from('5'), 5, 'Should return correct version from a string') t.equal(Version.from(0, 1), 1, 'Should return default value if version is invalid') t.equal(Version.from(null, 1), 1, 'Should return default value if version is undefined') t.end() }) test('Version capacity', function (t) { t.throws(function () { Version.getCapacity() }, 'Should throw if version is undefined') t.throws(function () { Version.getCapacity('') }, 'Should throw if version is not a number') t.throws(function () { Version.getCapacity(0) }, 'Should throw if version is not in range') t.throws(function () { Version.getCapacity(41) }, 'Should throw if version is not in range') for (let l = 0; l < EC_LEVELS.length; l++) { for (let i = 1; i <= 40; i++) { t.equal(Version.getCapacity(i, EC_LEVELS[l], Mode.NUMERIC), EXPECTED_NUMERIC_CAPACITY[i - 1][l], 'Should return correct numeric mode capacity') t.equal(Version.getCapacity(i, EC_LEVELS[l], Mode.ALPHANUMERIC), EXPECTED_ALPHANUMERIC_CAPACITY[i - 1][l], 'Should return correct alphanumeric mode capacity') t.equal(Version.getCapacity(i, EC_LEVELS[l], Mode.KANJI), EXPECTED_KANJI_CAPACITY[i - 1][l], 'Should return correct kanji mode capacity') t.equal(Version.getCapacity(i, EC_LEVELS[l], Mode.BYTE), EXPECTED_BYTE_CAPACITY[i - 1][l], 'Should return correct byte mode capacity') t.equal(Version.getCapacity(i, EC_LEVELS[l]), EXPECTED_BYTE_CAPACITY[i - 1][l], 'Should return correct byte mode capacity') } } t.end() }) test('Version best match', function (t) { function testBestVersionForCapacity (expectedCapacity, DataCtor) { for (let v = 0; v < 40; v++) { for (let l = 0; l < EC_LEVELS.length; l++) { const capacity = expectedCapacity[v][l] const data = new DataCtor(new Array(capacity + 1).join('-')) t.equal(Version.getBestVersionForData(data, EC_LEVELS[l]), v + 1, 'Should return best version') t.equal(Version.getBestVersionForData([data], EC_LEVELS[l]), v + 1, 'Should return best version') if (l === 1) { t.equal(Version.getBestVersionForData(data, null), v + 1, 'Should return best version for ECLevel.M if error level is undefined') t.equal(Version.getBestVersionForData([data], null), v + 1, 'Should return best version for ECLevel.M if error level is undefined') } } } for (let i = 0; i < EC_LEVELS.length; i++) { const exceededCapacity = expectedCapacity[39][i] + 1 const tooBigData = new DataCtor(new Array(exceededCapacity + 1).join('-')) const tooBigDataArray = [ new DataCtor(new Array(Math.floor(exceededCapacity / 2)).join('-')), new DataCtor(new Array(Math.floor(exceededCapacity / 2) + 1).join('-')) ] t.notOk(Version.getBestVersionForData(tooBigData, EC_LEVELS[i]), 'Should return undefined if data is too big') t.notOk(Version.getBestVersionForData([tooBigData], EC_LEVELS[i]), 'Should return undefined if data is too big') t.notOk(Version.getBestVersionForData(tooBigDataArray, EC_LEVELS[i]), 'Should return undefined if data is too big') } } testBestVersionForCapacity(EXPECTED_NUMERIC_CAPACITY, NumericData) testBestVersionForCapacity(EXPECTED_ALPHANUMERIC_CAPACITY, AlphanumericData) testBestVersionForCapacity(EXPECTED_KANJI_CAPACITY, KanjiData) testBestVersionForCapacity(EXPECTED_BYTE_CAPACITY, ByteData) t.ok(Version.getBestVersionForData([new ByteData('abc'), new NumericData('1234')]), 'Should return a version number if input array is valid') t.equal(Version.getBestVersionForData([]), 1, 'Should return 1 if array is empty') t.end() }) test('Version encoded info', function (t) { let v for (v = 0; v < 7; v++) { t.throws(function () { Version.getEncodedBits(v) }, 'Should throw if version is invalid or less than 7') } for (v = 7; v <= 40; v++) { const bch = Version.getEncodedBits(v) t.equal(bch, EXPECTED_VERSION_BITS[v - 7], 'Should return correct bits') } t.end() })