mirror of
https://github.com/dutchcoders/transfer.sh.git
synced 2024-12-13 14:20:18 +01:00
329 lines
6.5 KiB
Go
329 lines
6.5 KiB
Go
|
// go-qrcode
|
||
|
// Copyright 2014 Tom Harwood
|
||
|
|
||
|
package qrcode
|
||
|
|
||
|
import (
|
||
|
"fmt"
|
||
|
"reflect"
|
||
|
"testing"
|
||
|
|
||
|
bitset "github.com/skip2/go-qrcode/bitset"
|
||
|
)
|
||
|
|
||
|
func TestClassifyDataMode(t *testing.T) {
|
||
|
type Test struct {
|
||
|
}
|
||
|
|
||
|
tests := []struct {
|
||
|
data []byte
|
||
|
actual []segment
|
||
|
}{
|
||
|
{
|
||
|
[]byte{0x30},
|
||
|
[]segment{
|
||
|
{
|
||
|
dataModeNumeric,
|
||
|
[]byte{0x30},
|
||
|
},
|
||
|
},
|
||
|
},
|
||
|
{
|
||
|
[]byte{0x30, 0x41, 0x42, 0x43, 0x20, 0x00, 0xf0, 0xf1, 0xf2, 0x31},
|
||
|
[]segment{
|
||
|
{
|
||
|
dataModeNumeric,
|
||
|
[]byte{0x30},
|
||
|
},
|
||
|
{
|
||
|
dataModeAlphanumeric,
|
||
|
[]byte{0x41, 0x42, 0x43, 0x20},
|
||
|
},
|
||
|
{
|
||
|
dataModeByte,
|
||
|
[]byte{0x00, 0xf0, 0xf1, 0xf2},
|
||
|
},
|
||
|
{
|
||
|
dataModeNumeric,
|
||
|
[]byte{0x31},
|
||
|
},
|
||
|
},
|
||
|
},
|
||
|
}
|
||
|
|
||
|
for _, test := range tests {
|
||
|
encoder := newDataEncoder(dataEncoderType1To9)
|
||
|
encoder.encode(test.data)
|
||
|
|
||
|
if !reflect.DeepEqual(test.actual, encoder.actual) {
|
||
|
t.Errorf("Got %v, expected %v", encoder.actual, test.actual)
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func TestByteModeLengthCalculations(t *testing.T) {
|
||
|
tests := []struct {
|
||
|
dataEncoderType dataEncoderType
|
||
|
dataMode dataMode
|
||
|
numSymbols int
|
||
|
expectedLength int
|
||
|
}{}
|
||
|
|
||
|
for i, test := range tests {
|
||
|
encoder := newDataEncoder(test.dataEncoderType)
|
||
|
var resultLength int
|
||
|
|
||
|
resultLength, err := encoder.encodedLength(test.dataMode, test.numSymbols)
|
||
|
|
||
|
if test.expectedLength == -1 {
|
||
|
if err == nil {
|
||
|
t.Errorf("Test %d: got length %d, expected error", i, resultLength)
|
||
|
}
|
||
|
} else if resultLength != test.expectedLength {
|
||
|
t.Errorf("Test %d: got length %d, expected length %d", i, resultLength,
|
||
|
test.expectedLength)
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func TestSingleModeEncodings(t *testing.T) {
|
||
|
tests := []struct {
|
||
|
dataEncoderType dataEncoderType
|
||
|
dataMode dataMode
|
||
|
data string
|
||
|
expected *bitset.Bitset
|
||
|
}{
|
||
|
{
|
||
|
dataEncoderType1To9,
|
||
|
dataModeNumeric,
|
||
|
"01234567",
|
||
|
bitset.NewFromBase2String("0001 0000001000 0000001100 0101011001 1000011"),
|
||
|
},
|
||
|
{
|
||
|
dataEncoderType1To9,
|
||
|
dataModeAlphanumeric,
|
||
|
"AC-42",
|
||
|
bitset.NewFromBase2String("0010 000000101 00111001110 11100111001 000010"),
|
||
|
},
|
||
|
{
|
||
|
dataEncoderType1To9,
|
||
|
dataModeByte,
|
||
|
"123",
|
||
|
bitset.NewFromBase2String("0100 00000011 00110001 00110010 00110011"),
|
||
|
},
|
||
|
{
|
||
|
dataEncoderType10To26,
|
||
|
dataModeByte,
|
||
|
"123",
|
||
|
bitset.NewFromBase2String("0100 00000000 00000011 00110001 00110010 00110011"),
|
||
|
},
|
||
|
{
|
||
|
dataEncoderType27To40,
|
||
|
dataModeByte,
|
||
|
"123",
|
||
|
bitset.NewFromBase2String("0100 00000000 00000011 00110001 00110010 00110011"),
|
||
|
},
|
||
|
}
|
||
|
|
||
|
for _, test := range tests {
|
||
|
encoder := newDataEncoder(test.dataEncoderType)
|
||
|
encoded := bitset.New()
|
||
|
|
||
|
encoder.encodeDataRaw([]byte(test.data), test.dataMode, encoded)
|
||
|
|
||
|
if !test.expected.Equals(encoded) {
|
||
|
t.Errorf("For %s got %s, expected %s", test.data, encoded.String(),
|
||
|
test.expected.String())
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
type testModeSegment struct {
|
||
|
dataMode dataMode
|
||
|
numChars int
|
||
|
}
|
||
|
|
||
|
func TestOptimiseEncoding(t *testing.T) {
|
||
|
tests := []struct {
|
||
|
dataEncoderType dataEncoderType
|
||
|
actual []testModeSegment
|
||
|
optimised []testModeSegment
|
||
|
}{
|
||
|
// Coalescing multiple segments.
|
||
|
{
|
||
|
dataEncoderType1To9,
|
||
|
[]testModeSegment{
|
||
|
{dataModeAlphanumeric, 1}, // length = 4 + 9 + 6 = 19 bits
|
||
|
{dataModeNumeric, 1}, // length = 4 + 10 + 4 = 18 bits
|
||
|
{dataModeAlphanumeric, 1}, // 19 bits.
|
||
|
{dataModeNumeric, 1}, // 18 bits.
|
||
|
{dataModeAlphanumeric, 1}, // 19 bits.
|
||
|
// total = 93 bits.
|
||
|
},
|
||
|
[]testModeSegment{
|
||
|
{dataModeAlphanumeric, 5}, // length = 4 + 9 + 22 + 6 = 41.
|
||
|
},
|
||
|
},
|
||
|
// Coalesing not necessary.
|
||
|
{
|
||
|
dataEncoderType1To9,
|
||
|
[]testModeSegment{
|
||
|
{dataModeAlphanumeric, 1},
|
||
|
{dataModeNumeric, 20},
|
||
|
},
|
||
|
[]testModeSegment{
|
||
|
{dataModeAlphanumeric, 1},
|
||
|
{dataModeNumeric, 20},
|
||
|
},
|
||
|
},
|
||
|
// Switch to more general dataMode.
|
||
|
{
|
||
|
dataEncoderType1To9,
|
||
|
[]testModeSegment{
|
||
|
{dataModeAlphanumeric, 1},
|
||
|
{dataModeByte, 1},
|
||
|
{dataModeNumeric, 1},
|
||
|
},
|
||
|
[]testModeSegment{
|
||
|
{dataModeAlphanumeric, 1},
|
||
|
{dataModeByte, 2},
|
||
|
},
|
||
|
},
|
||
|
// https://www.google.com/123
|
||
|
// BBBBBAAABBBABBBBBBABBBANNN
|
||
|
{
|
||
|
dataEncoderType1To9,
|
||
|
[]testModeSegment{
|
||
|
{dataModeByte, 5},
|
||
|
{dataModeAlphanumeric, 3},
|
||
|
{dataModeByte, 3},
|
||
|
{dataModeAlphanumeric, 1},
|
||
|
{dataModeByte, 6},
|
||
|
{dataModeAlphanumeric, 1},
|
||
|
{dataModeAlphanumeric, 4},
|
||
|
{dataModeNumeric, 3},
|
||
|
},
|
||
|
[]testModeSegment{
|
||
|
{dataModeByte, 23},
|
||
|
{dataModeNumeric, 3},
|
||
|
},
|
||
|
},
|
||
|
// HTTPS://WWW.GOOGLE.COM/123
|
||
|
// AAAAAAAAAAAAAAAAAAAAAAANNN
|
||
|
{
|
||
|
dataEncoderType1To9,
|
||
|
[]testModeSegment{
|
||
|
{dataModeAlphanumeric, 23},
|
||
|
{dataModeNumeric, 3},
|
||
|
},
|
||
|
[]testModeSegment{
|
||
|
{dataModeAlphanumeric, 26},
|
||
|
},
|
||
|
},
|
||
|
{
|
||
|
dataEncoderType27To40,
|
||
|
[]testModeSegment{
|
||
|
{dataModeByte, 1},
|
||
|
{dataModeNumeric, 1},
|
||
|
{dataModeByte, 1},
|
||
|
{dataModeNumeric, 1},
|
||
|
{dataModeByte, 1},
|
||
|
{dataModeNumeric, 1},
|
||
|
{dataModeByte, 1},
|
||
|
{dataModeNumeric, 1},
|
||
|
},
|
||
|
[]testModeSegment{
|
||
|
{dataModeByte, 8},
|
||
|
},
|
||
|
},
|
||
|
}
|
||
|
|
||
|
for _, test := range tests {
|
||
|
numTotalChars := 0
|
||
|
for _, v := range test.actual {
|
||
|
numTotalChars += v.numChars
|
||
|
}
|
||
|
|
||
|
data := make([]byte, numTotalChars)
|
||
|
|
||
|
i := 0
|
||
|
for _, v := range test.actual {
|
||
|
for j := 0; j < v.numChars; j++ {
|
||
|
switch v.dataMode {
|
||
|
case dataModeNumeric:
|
||
|
data[i] = '1'
|
||
|
case dataModeAlphanumeric:
|
||
|
data[i] = 'A'
|
||
|
case dataModeByte:
|
||
|
data[i] = '#'
|
||
|
default:
|
||
|
t.Fatal("Unrecognised data mode")
|
||
|
}
|
||
|
|
||
|
i++
|
||
|
}
|
||
|
}
|
||
|
|
||
|
encoder := newDataEncoder(test.dataEncoderType)
|
||
|
|
||
|
_, err := encoder.encode(data)
|
||
|
|
||
|
if err != nil {
|
||
|
t.Errorf("Got %s, expected valid encoding", err.Error())
|
||
|
} else {
|
||
|
ok := true
|
||
|
|
||
|
if len(encoder.optimised) != len(test.optimised) {
|
||
|
ok = false
|
||
|
} else {
|
||
|
for i, s := range test.optimised {
|
||
|
if encoder.optimised[i].dataMode != s.dataMode ||
|
||
|
len(encoder.optimised[i].data) != s.numChars {
|
||
|
ok = false
|
||
|
break
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if !ok {
|
||
|
t.Errorf("got %s, expected %s", segmentsString(encoder.optimised),
|
||
|
testModeSegmentsString(test.optimised))
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func testModeSegmentsString(segments []testModeSegment) string {
|
||
|
result := "["
|
||
|
|
||
|
for i, segment := range segments {
|
||
|
if i > 0 {
|
||
|
result += ", "
|
||
|
}
|
||
|
|
||
|
result += fmt.Sprintf("%d*%s", segment.numChars,
|
||
|
dataModeString(segment.dataMode))
|
||
|
}
|
||
|
|
||
|
result += "]"
|
||
|
|
||
|
return result
|
||
|
}
|
||
|
|
||
|
func segmentsString(segments []segment) string {
|
||
|
result := "["
|
||
|
|
||
|
for i, segment := range segments {
|
||
|
if i > 0 {
|
||
|
result += ", "
|
||
|
}
|
||
|
|
||
|
result += fmt.Sprintf("%d*%s", len(segment.data),
|
||
|
dataModeString(segment.dataMode))
|
||
|
}
|
||
|
|
||
|
result += "]"
|
||
|
|
||
|
return result
|
||
|
}
|