diff options
Diffstat (limited to 'vendor/github.com/skip2/go-qrcode')
16 files changed, 2144 insertions, 0 deletions
diff --git a/vendor/github.com/skip2/go-qrcode/.gitignore b/vendor/github.com/skip2/go-qrcode/.gitignore new file mode 100644 index 0000000..bc1be2b --- /dev/null +++ b/vendor/github.com/skip2/go-qrcode/.gitignore @@ -0,0 +1,4 @@ +*.sw* +*.png +*.directory +qrcode/qrcode diff --git a/vendor/github.com/skip2/go-qrcode/.travis.yml b/vendor/github.com/skip2/go-qrcode/.travis.yml new file mode 100644 index 0000000..f8bd6cd --- /dev/null +++ b/vendor/github.com/skip2/go-qrcode/.travis.yml @@ -0,0 +1,8 @@ +language: go + +go: + - 1.3 + +script: + - go test -v ./... + diff --git a/vendor/github.com/skip2/go-qrcode/README.md b/vendor/github.com/skip2/go-qrcode/README.md new file mode 100644 index 0000000..2d07646 --- /dev/null +++ b/vendor/github.com/skip2/go-qrcode/README.md @@ -0,0 +1,74 @@ +# go-qrcode # + +<img src='https://skip.org/img/nyancat-youtube-qr.png' align='right'> + +Package qrcode implements a QR Code encoder. [](https://travis-ci.org/skip2/go-qrcode) + +A QR Code is a matrix (two-dimensional) barcode. Arbitrary content may be encoded, with URLs being a popular choice :) + +Each QR Code contains error recovery information to aid reading damaged or obscured codes. There are four levels of error recovery: Low, medium, high and highest. QR Codes with a higher recovery level are more robust to damage, at the cost of being physically larger. + +## Install + + go get -u github.com/skip2/go-qrcode/... + +A command-line tool `qrcode` will be built into `$GOPATH/bin/`. + +## Usage + + import qrcode "github.com/skip2/go-qrcode" + +- **Create a PNG image:** + + var png []byte + png, err := qrcode.Encode("https://example.org", qrcode.Medium, 256) + +- **Create a PNG image and write to a file:** + + err := qrcode.WriteFile("https://example.org", qrcode.Medium, 256, "qr.png") + +Both examples use the `qrcode.Medium` error Recovery Level and create a 256x256 pixel, black on white QR Code. + +The maximum capacity of a QR Code varies according to the content encoded and +the error recovery level. The maximum capacity is 2,953 bytes, 4,296 +alphanumeric characters, 7,089 numeric digits, or a combination of these. + +## Documentation + +[](https://godoc.org/github.com/skip2/go-qrcode) + +## Demoapp + +[http://go-qrcode.appspot.com](http://go-qrcode.appspot.com) + +## CLI + +A command-line tool `qrcode` will be built into `$GOPATH/bin/`. + +``` +qrcode -- QR Code encoder in Go +https://github.com/skip2/go-qrcode + +Flags: + -o string + out PNG file prefix, empty for stdout + -s int + image size (pixel) (default 256) + +Usage: + 1. Arguments except for flags are joined by " " and used to generate QR code. + Default output is STDOUT, pipe to imagemagick command "display" to display + on any X server. + + qrcode hello word | display + + 2. Save to file if "display" not available: + + qrcode "homepage: https://github.com/skip2/go-qrcode" > out.png +``` + +## Links + +- [http://en.wikipedia.org/wiki/QR_code](http://en.wikipedia.org/wiki/QR_code) +- [ISO/IEC 18004:2006](http://www.iso.org/iso/catalogue_detail.htm?csnumber=43655) - Main QR Code specification (approx CHF 198,00)<br> +- [https://github.com/qpliu/qrencode-go/](https://github.com/qpliu/qrencode-go/) - alternative Go QR encoding library based on [ZXing](https://github.com/zxing/zxing) diff --git a/vendor/github.com/skip2/go-qrcode/bitset/bitset_test.go b/vendor/github.com/skip2/go-qrcode/bitset/bitset_test.go new file mode 100644 index 0000000..e755a15 --- /dev/null +++ b/vendor/github.com/skip2/go-qrcode/bitset/bitset_test.go @@ -0,0 +1,321 @@ +// go-qrcode +// Copyright 2014 Tom Harwood + +package bitset + +import ( + rand "math/rand" + "testing" +) + +func TestNewBitset(t *testing.T) { + tests := [][]bool{ + {}, + {b1}, + {b0}, + {b1, b0}, + {b1, b0, b1}, + {b0, b0, b1}, + } + + for _, v := range tests { + result := New(v...) + + if !equal(result.Bits(), v) { + t.Errorf("%s", result.String()) + t.Errorf("%v => %v, want %v", v, result.Bits(), v) + } + } +} + +func TestAppend(t *testing.T) { + randomBools := make([]bool, 128) + + rng := rand.New(rand.NewSource(1)) + + for i := 0; i < len(randomBools); i++ { + randomBools[i] = rng.Intn(2) == 1 + } + + for i := 0; i < len(randomBools)-1; i++ { + a := New(randomBools[0:i]...) + b := New(randomBools[i:]...) + + a.Append(b) + + if !equal(a.Bits(), randomBools) { + t.Errorf("got %v, want %v", a.Bits(), randomBools) + } + } +} + +func TestAppendByte(t *testing.T) { + tests := []struct { + initial *Bitset + value byte + numBits int + expected *Bitset + }{ + { + New(), + 0x01, + 1, + New(b1), + }, + { + New(b1), + 0x01, + 1, + New(b1, b1), + }, + { + New(b0), + 0x01, + 1, + New(b0, b1), + }, + { + New(b1, b0, b1, b0, b1, b0, b1), + 0xAA, // 0b10101010 + 2, + New(b1, b0, b1, b0, b1, b0, b1, b1, b0), + }, + { + New(b1, b0, b1, b0, b1, b0, b1), + 0xAA, // 0b10101010 + 8, + New(b1, b0, b1, b0, b1, b0, b1, b1, b0, b1, b0, b1, b0, b1, b0), + }, + } + + for _, test := range tests { + test.initial.AppendByte(test.value, test.numBits) + if !equal(test.initial.Bits(), test.expected.Bits()) { + t.Errorf("Got %v, expected %v", test.initial.Bits(), + test.expected.Bits()) + } + } +} + +func TestAppendUint32(t *testing.T) { + tests := []struct { + initial *Bitset + value uint32 + numBits int + expected *Bitset + }{ + { + New(), + 0xAAAAAAAF, + 4, + New(b1, b1, b1, b1), + }, + { + New(), + 0xFFFFFFFF, + 32, + New(b1, b1, b1, b1, b1, b1, b1, b1, b1, b1, b1, b1, b1, b1, b1, b1, b1, + b1, b1, b1, b1, b1, b1, b1, b1, b1, b1, b1, b1, b1, b1, b1), + }, + { + New(), + 0x0, + 32, + New(b0, b0, b0, b0, b0, b0, b0, b0, b0, b0, b0, b0, b0, b0, b0, b0, b0, + b0, b0, b0, b0, b0, b0, b0, b0, b0, b0, b0, b0, b0, b0, b0), + }, + { + New(), + 0xAAAAAAAA, + 32, + New(b1, b0, b1, b0, b1, b0, b1, b0, b1, b0, b1, b0, b1, b0, b1, b0, b1, + b0, b1, b0, b1, b0, b1, b0, b1, b0, b1, b0, b1, b0, b1, b0), + }, + { + New(), + 0xAAAAAAAA, + 31, + New(b0, b1, b0, b1, b0, b1, b0, b1, b0, b1, b0, b1, b0, b1, b0, b1, + b0, b1, b0, b1, b0, b1, b0, b1, b0, b1, b0, b1, b0, b1, b0), + }, + } + + for _, test := range tests { + test.initial.AppendUint32(test.value, test.numBits) + if !equal(test.initial.Bits(), test.expected.Bits()) { + t.Errorf("Got %v, expected %v", test.initial.Bits(), + test.expected.Bits()) + } + } +} + +func TestAppendBools(t *testing.T) { + randomBools := make([]bool, 128) + + rng := rand.New(rand.NewSource(1)) + + for i := 0; i < len(randomBools); i++ { + randomBools[i] = rng.Intn(2) == 1 + } + + for i := 0; i < len(randomBools)-1; i++ { + result := New(randomBools[0:i]...) + result.AppendBools(randomBools[i:]...) + + if !equal(result.Bits(), randomBools) { + t.Errorf("got %v, want %v", result.Bits(), randomBools) + } + } +} + +func BenchmarkShortAppend(b *testing.B) { + bitset := New() + + for i := 0; i < b.N; i++ { + bitset.AppendBools(b0, b1, b0, b1, b0, b1, b0) + } +} + +func TestLen(t *testing.T) { + randomBools := make([]bool, 128) + + rng := rand.New(rand.NewSource(1)) + + for i := 0; i < len(randomBools); i++ { + randomBools[i] = rng.Intn(2) == 1 + } + + for i := 0; i < len(randomBools)-1; i++ { + result := New(randomBools[0:i]...) + + if result.Len() != i { + t.Errorf("Len = %d, want %d", result.Len(), i) + } + } +} + +func TestAt(t *testing.T) { + test := []bool{b0, b1, b0, b1, b0, b1, b1, b0, b1} + + bitset := New(test...) + for i, v := range test { + result := bitset.At(i) + + if result != test[i] { + t.Errorf("bitset[%d] => %t, want %t", i, result, v) + } + } +} + +func equal(a []bool, b []bool) bool { + if len(a) != len(b) { + return false + } + + for i := 0; i < len(a); i++ { + if a[i] != b[i] { + return false + } + } + + return true +} + +func TestExample(t *testing.T) { + b := New() // {} + b.AppendBools(true, true, false) // {1, 1, 0} + b.AppendBools(true) // {1, 1, 0, 1} + b.AppendByte(0x02, 4) // {1, 1, 0, 1, 0, 0, 1, 0} + + expected := []bool{b1, b1, b0, b1, b0, b0, b1, b0} + + if !equal(b.Bits(), expected) { + t.Errorf("Got %v, expected %v", b.Bits(), expected) + } +} + +func TestByteAt(t *testing.T) { + data := []bool{b0, b1, b0, b1, b0, b1, b1, b0, b1} + + tests := []struct { + index int + expected byte + }{ + { + 0, + 0x56, + }, + { + 1, + 0xad, + }, + { + 2, + 0x2d, + }, + { + 5, + 0x0d, + }, + { + 8, + 0x01, + }, + } + + for _, test := range tests { + b := New() + b.AppendBools(data...) + + result := b.ByteAt(test.index) + + if result != test.expected { + t.Errorf("Got %#x, expected %#x", result, test.expected) + } + } +} + +func TestSubstr(t *testing.T) { + data := []bool{b0, b1, b0, b1, b0, b1, b1, b0} + + tests := []struct { + start int + end int + expected []bool + }{ + { + 0, + 8, + []bool{b0, b1, b0, b1, b0, b1, b1, b0}, + }, + { + 0, + 0, + []bool{}, + }, + { + 0, + 1, + []bool{b0}, + }, + { + 2, + 4, + []bool{b0, b1}, + }, + } + + for _, test := range tests { + b := New() + b.AppendBools(data...) + + result := b.Substr(test.start, test.end) + + expected := New() + expected.AppendBools(test.expected...) + + if !result.Equals(expected) { + t.Errorf("Got %s, expected %s", result.String(), expected.String()) + } + } +} diff --git a/vendor/github.com/skip2/go-qrcode/encoder_test.go b/vendor/github.com/skip2/go-qrcode/encoder_test.go new file mode 100644 index 0000000..1bf74be --- /dev/null +++ b/vendor/github.com/skip2/go-qrcode/encoder_test.go @@ -0,0 +1,328 @@ +// 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 +} diff --git a/vendor/github.com/skip2/go-qrcode/example_test.go b/vendor/github.com/skip2/go-qrcode/example_test.go new file mode 100644 index 0000000..e4a7c46 --- /dev/null +++ b/vendor/github.com/skip2/go-qrcode/example_test.go @@ -0,0 +1,34 @@ +// go-qrcode +// Copyright 2014 Tom Harwood + +package qrcode + +import ( + "fmt" + "os" +) + +func ExampleEncode() { + var png []byte + png, err := Encode("https://example.org", Medium, 256) + + if err != nil { + fmt.Printf("Error: %s", err.Error()) + } else { + fmt.Printf("PNG is %d bytes long", len(png)) + } +} + +func ExampleWriteFile() { + filename := "example.png" + + err := WriteFile("https://example.org", Medium, 256, filename) + + if err != nil { + err = os.Remove(filename) + } + + if err != nil { + fmt.Printf("Error: %s", err.Error()) + } +} diff --git a/vendor/github.com/skip2/go-qrcode/qrcode.go b/vendor/github.com/skip2/go-qrcode/qrcode.go index 49f8b4b..6efcf3e 100644 --- a/vendor/github.com/skip2/go-qrcode/qrcode.go +++ b/vendor/github.com/skip2/go-qrcode/qrcode.go @@ -41,6 +41,7 @@ import ( "image" "image/color" "image/png" + "io" "io/ioutil" "log" "os" @@ -278,6 +279,22 @@ func (q *QRCode) PNG(size int) ([]byte, error) { return b.Bytes(), nil } +// Write writes the QR Code as a PNG image to io.Writer. +// +// size is both the image width and height in pixels. If size is too small then +// a larger image is silently written. +func (q *QRCode) Write(size int, out io.Writer) error { + var png []byte + + png, err := q.PNG(size) + + if err != nil { + return err + } + _, err = out.Write(png) + return err +} + // WriteFile writes the QR Code as a PNG image to the specified file. // // size is both the image width and height in pixels. If size is too small then diff --git a/vendor/github.com/skip2/go-qrcode/qrcode/main.go b/vendor/github.com/skip2/go-qrcode/qrcode/main.go new file mode 100644 index 0000000..ab7c8d8 --- /dev/null +++ b/vendor/github.com/skip2/go-qrcode/qrcode/main.go @@ -0,0 +1,76 @@ +// go-qrcode +// Copyright 2014 Tom Harwood + +package main + +import ( + "flag" + "fmt" + "os" + "strings" + + qrcode "github.com/skip2/go-qrcode" +) + +func main() { + outFile := flag.String("o", "", "out PNG file prefix, empty for stdout") + size := flag.Int("s", 256, "image size (pixel)") + flag.Usage = func() { + fmt.Fprintf(os.Stderr, `qrcode -- QR Code encoder in Go +https://github.com/skip2/go-qrcode + +Flags: +`) + flag.PrintDefaults() + fmt.Fprintf(os.Stderr, ` +Usage: + 1. Arguments except for flags are joined by " " and used to generate QR code. + Default output is STDOUT, pipe to imagemagick command "display" to display + on any X server. + + qrcode hello word | display + + 2. Save to file if "display" not available: + + qrcode "homepage: https://github.com/skip2/go-qrcode" > out.png + +`) + } + flag.Parse() + + if *size <= 0 { + checkError(fmt.Errorf("Error: value of -s should > 0")) + } + if len(flag.Args()) == 0 { + flag.Usage() + checkError(fmt.Errorf("Error: no content given")) + } + + content := strings.Join(flag.Args(), " ") + + var err error + var q *qrcode.QRCode + q, err = qrcode.New(content, qrcode.Highest) + checkError(err) + + var png []byte + png, err = q.PNG(*size) + checkError(err) + + if *outFile == "" { + os.Stdout.Write(png) + } else { + var fh *os.File + fh, err = os.Create(*outFile + ".png") + checkError(err) + defer fh.Close() + fh.Write(png) + } +} + +func checkError(err error) { + if err != nil { + fmt.Fprintf(os.Stderr, "%s\n", err) + os.Exit(0) + } +} diff --git a/vendor/github.com/skip2/go-qrcode/qrcode_decode_test.go b/vendor/github.com/skip2/go-qrcode/qrcode_decode_test.go new file mode 100644 index 0000000..870640b --- /dev/null +++ b/vendor/github.com/skip2/go-qrcode/qrcode_decode_test.go @@ -0,0 +1,232 @@ +// go-qrcode +// Copyright 2014 Tom Harwood + +package qrcode + +import ( + "bytes" + "flag" + "fmt" + "math/rand" + "os/exec" + "strings" + "testing" +) + +// These tests use zbarimg to decode generated QR Codes to ensure they are +// readable. sudo apt-get install zbar-tools, or download from +// http://zbar.sourceforge.net. +// +// By default these tests are disabled to avoid a dependency on zbarimg if +// you're not running the tests. Use the -test-decode flag (go test +// -test-decode) to enable. + +var testDecode *bool = flag.Bool("test-decode", + false, + "Enable decode tests. Requires zbarimg installed.") + +var testDecodeFuzz *bool = flag.Bool("test-decode-fuzz", + false, + "Enable decode fuzz tests. Requires zbarimg installed.") + +func TestDecodeBasic(t *testing.T) { + if !*testDecode { + t.Skip("Decode tests not enabled") + } + + tests := []struct { + content string + numRepetitions int + level RecoveryLevel + }{ + { + "A", + 1, + Low, + }, + { + "A", + 1, + Medium, + }, + { + "A", + 1, + High, + }, + { + "A", + 1, + Highest, + }, + { + "01234567", + 1, + Medium, + }, + } + + for _, test := range tests { + content := strings.Repeat(test.content, test.numRepetitions) + + q, err := New(content, test.level) + if err != nil { + t.Error(err.Error()) + } + + err = zbarimgCheck(q) + + if err != nil { + t.Error(err.Error()) + } + } +} + +func TestDecodeAllVersionLevels(t *testing.T) { + if !*testDecode { + t.Skip("Decode tests not enabled") + } + + for version := 1; version <= 40; version++ { + for _, level := range []RecoveryLevel{Low, Medium, High, Highest} { + t.Logf("Version=%d Level=%d", + version, + level) + + q, err := newWithForcedVersion( + fmt.Sprintf("v-%d l-%d", version, level), version, level) + if err != nil { + t.Fatal(err.Error()) + return + } + + err = zbarimgCheck(q) + + if err != nil { + t.Errorf("Version=%d Level=%d, err=%s, expected success", + version, + level, + err.Error()) + continue + } + } + } +} + +func TestDecodeAllCharacters(t *testing.T) { + if !*testDecode { + t.Skip("Decode tests not enabled") + } + + var content string + + // zbarimg has trouble with null bytes, hence start from ASCII 1. + for i := 1; i < 256; i++ { + content += string(i) + } + + q, err := New(content, Low) + if err != nil { + t.Error(err.Error()) + } + + err = zbarimgCheck(q) + + if err != nil { + t.Error(err.Error()) + } +} + +func TestDecodeFuzz(t *testing.T) { + if !*testDecodeFuzz { + t.Skip("Decode fuzz tests not enabled") + } + + r := rand.New(rand.NewSource(0)) + + const iterations int = 32 + const maxLength int = 128 + + for i := 0; i < iterations; i++ { + len := r.Intn(maxLength-1) + 1 + + var content string + for j := 0; j < len; j++ { + // zbarimg seems to have trouble with special characters, test printable + // characters only for now. + content += string(32 + r.Intn(94)) + } + + for _, level := range []RecoveryLevel{Low, Medium, High, Highest} { + q, err := New(content, level) + if err != nil { + t.Error(err.Error()) + } + + err = zbarimgCheck(q) + + if err != nil { + t.Error(err.Error()) + } + } + } +} + +func zbarimgCheck(q *QRCode) error { + s, err := zbarimgDecode(q) + if err != nil { + return err + } + + if s != q.Content { + q.WriteFile(256, fmt.Sprintf("%x.png", q.Content)) + return fmt.Errorf("got '%s' (%x) expected '%s' (%x)", s, s, q.Content, q.Content) + } + + return nil +} + +func zbarimgDecode(q *QRCode) (string, error) { + var png []byte + + // 512x512px + png, err := q.PNG(512) + if err != nil { + return "", err + } + + cmd := exec.Command("zbarimg", "--quiet", "-Sdisable", + "-Sqrcode.enable", "/dev/stdin") + + var out bytes.Buffer + + cmd.Stdin = bytes.NewBuffer(png) + cmd.Stdout = &out + + err = cmd.Run() + + if err != nil { + return "", err + } + + return strings.TrimSuffix(strings.TrimPrefix(out.String(), "QR-Code:"), "\n"), nil +} + +func BenchmarkDecodeTest(b *testing.B) { + if !*testDecode { + b.Skip("Decode benchmarks not enabled") + } + + for n := 0; n < b.N; n++ { + q, err := New("content", Medium) + if err != nil { + b.Error(err.Error()) + } + + err = zbarimgCheck(q) + + if err != nil { + b.Error(err.Error()) + } + } +} diff --git a/vendor/github.com/skip2/go-qrcode/qrcode_test.go b/vendor/github.com/skip2/go-qrcode/qrcode_test.go new file mode 100644 index 0000000..258f792 --- /dev/null +++ b/vendor/github.com/skip2/go-qrcode/qrcode_test.go @@ -0,0 +1,173 @@ +// go-qrcode +// Copyright 2014 Tom Harwood + +package qrcode + +import ( + "strings" + "testing" +) + +func TestQRCodeMaxCapacity(t *testing.T) { + if testing.Short() { + t.Skip("Skipping TestQRCodeCapacity") + } + + tests := []struct { + string string + numRepetitions int + }{ + { + "0", + 7089, + }, + { + "A", + 4296, + }, + { + "#", + 2953, + }, + // Alternate byte/numeric data types. Optimises to 2,952 bytes. + { + "#1", + 1476, + }, + } + + for _, test := range tests { + _, err := New(strings.Repeat(test.string, test.numRepetitions), Low) + + if err != nil { + t.Errorf("%d x '%s' got %s expected success", test.numRepetitions, + test.string, err.Error()) + } + } + + for _, test := range tests { + _, err := New(strings.Repeat(test.string, test.numRepetitions+1), Low) + + if err == nil { + t.Errorf("%d x '%s' chars encodable, expected not encodable", + test.numRepetitions+1, test.string) + } + } +} + +func TestQRCodeVersionCapacity(t *testing.T) { + tests := []struct { + version int + level RecoveryLevel + maxNumeric int + maxAlphanumeric int + maxByte int + }{ + { + 1, + Low, + 41, + 25, + 17, + }, + { + 2, + Low, + 77, + 47, + 32, + }, + { + 2, + Highest, + 34, + 20, + 14, + }, + { + 40, + Low, + 7089, + 4296, + 2953, + }, + { + 40, + Highest, + 3057, + 1852, + 1273, + }, + } + + for i, test := range tests { + numericData := strings.Repeat("1", test.maxNumeric) + alphanumericData := strings.Repeat("A", test.maxAlphanumeric) + byteData := strings.Repeat("#", test.maxByte) + + var n *QRCode + var a *QRCode + var b *QRCode + var err error + + n, err = New(numericData, test.level) + if err != nil { + t.Fatal(err.Error()) + } + + a, err = New(alphanumericData, test.level) + if err != nil { + t.Fatal(err.Error()) + } + + b, err = New(byteData, test.level) + if err != nil { + t.Fatal(err.Error()) + } + + if n.VersionNumber != test.version { + t.Fatalf("Test #%d numeric has version #%d, expected #%d", i, + n.VersionNumber, test.version) + } + + if a.VersionNumber != test.version { + t.Fatalf("Test #%d alphanumeric has version #%d, expected #%d", i, + a.VersionNumber, test.version) + } + + if b.VersionNumber != test.version { + t.Fatalf("Test #%d byte has version #%d, expected #%d", i, + b.VersionNumber, test.version) + } + } +} + +func TestQRCodeISOAnnexIExample(t *testing.T) { + var q *QRCode + q, err := New("01234567", Medium) + + if err != nil { + t.Fatalf("Error producing ISO Annex I Example: %s, expected success", + err.Error()) + } + + const expectedMask int = 2 + + if q.mask != 2 { + t.Errorf("ISO Annex I example mask got %d, expected %d\n", q.mask, + expectedMask) + } +} + +func BenchmarkQRCodeURLSize(b *testing.B) { + for n := 0; n < b.N; n++ { + New("http://www.example.org", Medium) + } +} + +func BenchmarkQRCodeMaximumSize(b *testing.B) { + for n := 0; n < b.N; n++ { + // 7089 is the maximum encodable number of numeric digits. + New(strings.Repeat("0", 7089), Low) + } +} diff --git a/vendor/github.com/skip2/go-qrcode/reedsolomon/gf2_8_test.go b/vendor/github.com/skip2/go-qrcode/reedsolomon/gf2_8_test.go new file mode 100644 index 0000000..ab53d8a --- /dev/null +++ b/vendor/github.com/skip2/go-qrcode/reedsolomon/gf2_8_test.go @@ -0,0 +1,83 @@ +// go-qrcode +// Copyright 2014 Tom Harwood + +package reedsolomon + +import "testing" + +func TestGFMultiplicationIdentities(t *testing.T) { + for i := 0; i < 256; i++ { + value := gfElement(i) + if gfMultiply(gfZero, value) != gfZero { + t.Errorf("0 . %d != 0", value) + } + + if gfMultiply(value, gfOne) != value { + t.Errorf("%d . 1 == %d, want %d", value, gfMultiply(value, gfOne), value) + } + } +} + +func TestGFMultiplicationAndDivision(t *testing.T) { + // a * b == result + var tests = []struct { + a gfElement + b gfElement + result gfElement + }{ + {0, 29, 0}, + {1, 1, 1}, + {1, 32, 32}, + {2, 4, 8}, + {16, 128, 232}, + {17, 17, 28}, + {27, 9, 195}, + } + + for _, test := range tests { + result := gfMultiply(test.a, test.b) + + if result != test.result { + t.Errorf("%d * %d = %d, want %d", test.a, test.b, result, test.result) + } + + if test.b != gfZero && test.result != gfZero { + b := gfDivide(test.result, test.a) + + if b != test.b { + t.Errorf("%d / %d = %d, want %d", test.result, test.a, b, test.b) + } + } + } +} + +func TestGFInverse(t *testing.T) { + for i := 1; i < 256; i++ { + a := gfElement(i) + inverse := gfInverse(a) + + result := gfMultiply(a, inverse) + + if result != gfOne { + t.Errorf("%d * %d^-1 == %d, want %d", a, inverse, result, gfOne) + } + } +} + +func TestGFDivide(t *testing.T) { + for i := 1; i < 256; i++ { + for j := 1; j < 256; j++ { + // a * b == product + a := gfElement(i) + b := gfElement(j) + product := gfMultiply(a, b) + + // product / b == a + result := gfDivide(product, b) + + if result != a { + t.Errorf("%d / %d == %d, want %d", product, b, result, a) + } + } + } +} diff --git a/vendor/github.com/skip2/go-qrcode/reedsolomon/gf_poly_test.go b/vendor/github.com/skip2/go-qrcode/reedsolomon/gf_poly_test.go new file mode 100644 index 0000000..bcf2aab --- /dev/null +++ b/vendor/github.com/skip2/go-qrcode/reedsolomon/gf_poly_test.go @@ -0,0 +1,182 @@ +// go-qrcode +// Copyright 2014 Tom Harwood + +package reedsolomon + +import ( + "testing" +) + +func TestGFPolyAdd(t *testing.T) { + // a + b == result + var tests = []struct { + a gfPoly + b gfPoly + result gfPoly + }{ + { + gfPoly{[]gfElement{0, 0, 0}}, + gfPoly{[]gfElement{0}}, + gfPoly{[]gfElement{}}, + }, + { + gfPoly{[]gfElement{1, 0}}, + gfPoly{[]gfElement{1, 0}}, + gfPoly{[]gfElement{0, 0}}, + }, + { + gfPoly{[]gfElement{0xA0, 0x80, 0xFF, 0x00}}, + gfPoly{[]gfElement{0x0A, 0x82}}, + gfPoly{[]gfElement{0xAA, 0x02, 0xFF}}, + }, + } + + for _, test := range tests { + result := gfPolyAdd(test.a, test.b) + + if !test.result.equals(result) { + t.Errorf("%s * %s != %s (got %s)\n", test.a.string(false), test.b.string(false), + test.result.string(false), result.string(false)) + } + + if len(result.term) > 0 && result.term[len(result.term)-1] == 0 { + t.Errorf("Result's maximum term coefficient is zero") + } + } +} + +func TestGFPolyequals(t *testing.T) { + // a == b if isEqual + var tests = []struct { + a gfPoly + b gfPoly + isEqual bool + }{ + { + gfPoly{[]gfElement{0}}, + gfPoly{[]gfElement{0}}, + true, + }, + { + gfPoly{[]gfElement{1}}, + gfPoly{[]gfElement{0}}, + false, + }, + { + gfPoly{[]gfElement{1, 0, 1, 0, 1}}, + gfPoly{[]gfElement{1, 0, 1, 0, 1}}, + true, + }, + { + gfPoly{[]gfElement{1, 0, 1}}, + gfPoly{[]gfElement{1, 0, 1, 0, 0}}, + true, + }, + } + + for _, test := range tests { + isEqual := test.a.equals(test.b) + + if isEqual != test.isEqual { + t.Errorf("%s and %s equality is %t (got %t)\n", test.a.string(false), test.b.string(false), + test.isEqual, isEqual) + } + } +} + +func TestGFPolyMultiply(t *testing.T) { + // a * b == result + var tests = []struct { + a gfPoly + b gfPoly + result gfPoly + }{ + { + gfPoly{[]gfElement{0, 0, 1}}, + gfPoly{[]gfElement{9}}, + gfPoly{[]gfElement{0, 0, 9}}, + }, + { + gfPoly{[]gfElement{0, 16, 1}}, + gfPoly{[]gfElement{128, 2}}, + gfPoly{[]gfElement{0, 232, 160, 2}}, + }, + { + gfPoly{[]gfElement{254, 120, 88, 44, 11, 1}}, + gfPoly{[]gfElement{16, 2, 0, 51, 44}}, + gfPoly{[]gfElement{91, 50, 25, 184, 194, 105, 45, 244, 58, 44}}, + }, + } + + for _, test := range tests { + result := gfPolyMultiply(test.a, test.b) + + if !test.result.equals(result) { + t.Errorf("%s * %s = %s (got %s)\n", + test.a.string(false), + test.b.string(false), + test.result.string(false), + result.string(false)) + } + } +} + +func TestGFPolyRemainder(t *testing.T) { + // numerator / denominator == quotient + remainder. + var tests = []struct { + numerator gfPoly + denominator gfPoly + remainder gfPoly + }{ + { + gfPoly{[]gfElement{1}}, + gfPoly{[]gfElement{1}}, + gfPoly{[]gfElement{0}}, + }, + { + gfPoly{[]gfElement{1, 0}}, + gfPoly{[]gfElement{1}}, + gfPoly{[]gfElement{0}}, + }, + { + gfPoly{[]gfElement{1}}, + gfPoly{[]gfElement{1, 0}}, + gfPoly{[]gfElement{1}}, + }, + { + gfPoly{[]gfElement{1, 0, 1}}, + gfPoly{[]gfElement{0, 1}}, + gfPoly{[]gfElement{1}}, + }, + // (x^12 + x^10) / (x^10 + x^8 + x^5 + x^4 + x^2 + x^1 + x^0) = + // (x^10 + x^8 + x^5 + x^4 + x^2 + x^1 + x^0) * x^2 + + // (x^7 + x^6 + x^4 + x^3 + x^2) (the remainder) + { + gfPoly{[]gfElement{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1}}, + gfPoly{[]gfElement{1, 1, 1, 0, 1, 1, 0, 0, 1, 0, 1}}, + gfPoly{[]gfElement{0, 0, 1, 1, 1, 0, 1, 1}}, + }, + { + gfPoly{[]gfElement{91, 50, 25, 184, 194, 105, 45, 244, 58, 44}}, + gfPoly{[]gfElement{254, 120, 88, 44, 11, 1}}, + gfPoly{[]gfElement{}}, + }, + { + gfPoly{[]gfElement{0, 0, 0, 0, 0, 0, 195, 172, 24, 64}}, + gfPoly{[]gfElement{116, 147, 63, 198, 31, 1}}, + gfPoly{[]gfElement{48, 174, 34, 13, 134}}, + }, + } + + for _, test := range tests { + remainder := gfPolyRemainder(test.numerator, test.denominator) + + if !test.remainder.equals(remainder) { + t.Errorf("%s / %s, remainder = %s (got %s)\n", + test.numerator.string(false), + test.denominator.string(false), + test.remainder.string(false), + remainder.string(false)) + } + } +} diff --git a/vendor/github.com/skip2/go-qrcode/reedsolomon/reed_solomon_test.go b/vendor/github.com/skip2/go-qrcode/reedsolomon/reed_solomon_test.go new file mode 100644 index 0000000..88948a2 --- /dev/null +++ b/vendor/github.com/skip2/go-qrcode/reedsolomon/reed_solomon_test.go @@ -0,0 +1,89 @@ +// go-qrcode +// Copyright 2014 Tom Harwood + +package reedsolomon + +import ( + "testing" + + bitset "github.com/skip2/go-qrcode/bitset" +) + +func TestGeneratorPoly(t *testing.T) { + var tests = []struct { + degree int + generator gfPoly + }{ + // x^2 + 3x^1 + 2x^0 (the shortest generator poly) + { + 2, + gfPoly{term: []gfElement{2, 3, 1}}, + }, + // x^5 + 31x^4 + 198x^3 + 63x^2 + 147x^1 + 116x^0 + { + 5, + gfPoly{term: []gfElement{116, 147, 63, 198, 31, 1}}, + }, + // x^68 + 131x^67 + 115x^66 + 9x^65 + 39x^64 + 18x^63 + 182x^62 + 60x^61 + + // 94x^60 + 223x^59 + 230x^58 + 157x^57 + 142x^56 + 119x^55 + 85x^54 + + // 107x^53 + 34x^52 + 174x^51 + 167x^50 + 109x^49 + 20x^48 + 185x^47 + + // 112x^46 + 145x^45 + 172x^44 + 224x^43 + 170x^42 + 182x^41 + 107x^40 + + // 38x^39 + 107x^38 + 71x^37 + 246x^36 + 230x^35 + 225x^34 + 144x^33 + + // 20x^32 + 14x^31 + 175x^30 + 226x^29 + 245x^28 + 20x^27 + 219x^26 + + // 212x^25 + 51x^24 + 158x^23 + 88x^22 + 63x^21 + 36x^20 + 199x^19 + 4x^18 + + // 80x^17 + 157x^16 + 211x^15 + 239x^14 + 255x^13 + 7x^12 + 119x^11 + 11x^10 + // + 235x^9 + 12x^8 + 34x^7 + 149x^6 + 204x^5 + 8x^4 + 32x^3 + 29x^2 + 99x^1 + // + 11x^0 (the longest generator poly) + { + 68, + gfPoly{term: []gfElement{11, 99, 29, 32, 8, 204, 149, 34, 12, + 235, 11, 119, 7, 255, 239, 211, 157, 80, 4, 199, 36, 63, 88, 158, 51, 212, + 219, 20, 245, 226, 175, 14, 20, 144, 225, 230, 246, 71, 107, 38, 107, 182, + 170, 224, 172, 145, 112, 185, 20, 109, 167, 174, 34, 107, 85, 119, 142, + 157, 230, 223, 94, 60, 182, 18, 39, 9, 115, 131, 1}}, + }, + } + + for _, test := range tests { + generator := rsGeneratorPoly(test.degree) + + if !generator.equals(test.generator) { + t.Errorf("degree=%d generator=%s, want %s", test.degree, + generator.string(true), test.generator.string(true)) + } + } +} + +func TestEncode(t *testing.T) { + var tests = []struct { + numECBytes int + data string + rsCode string + }{ + { + 5, + "01000000 00011000 10101100 11000011 00000000", + "01000000 00011000 10101100 11000011 00000000 10000110 00001101 00100010 10101110 00110000", + }, + { + 10, + "00010000 00100000 00001100 01010110 01100001 10000000 11101100 00010001 11101100 00010001 11101100 00010001 11101100 00010001 11101100 00010001", + "00010000 00100000 00001100 01010110 01100001 10000000 11101100 00010001 11101100 00010001 11101100 00010001 11101100 00010001 11101100 00010001 10100101 00100100 11010100 11000001 11101101 00110110 11000111 10000111 00101100 01010101", + }, + } + + for _, test := range tests { + data := bitset.NewFromBase2String(test.data) + rsCode := bitset.NewFromBase2String(test.rsCode) + + result := Encode(data, test.numECBytes) + + if !rsCode.Equals(result) { + t.Errorf("data=%s, numECBytes=%d, encoded=%s, want %s", + data.String(), + test.numECBytes, + result.String(), + rsCode) + } + } +} diff --git a/vendor/github.com/skip2/go-qrcode/regular_symbol_test.go b/vendor/github.com/skip2/go-qrcode/regular_symbol_test.go new file mode 100644 index 0000000..9e274db --- /dev/null +++ b/vendor/github.com/skip2/go-qrcode/regular_symbol_test.go @@ -0,0 +1,31 @@ +// go-qrcode +// Copyright 2014 Tom Harwood + +package qrcode + +import ( + "fmt" + "testing" + + bitset "github.com/skip2/go-qrcode/bitset" +) + +func TestBuildRegularSymbol(t *testing.T) { + for k := 0; k <= 7; k++ { + v := getQRCodeVersion(Low, 1) + + data := bitset.New() + for i := 0; i < 26; i++ { + data.AppendNumBools(8, false) + } + + s, err := buildRegularSymbol(*v, k, data) + + if err != nil { + fmt.Println(err.Error()) + } else { + _ = s + //fmt.Print(m.string()) + } + } +} diff --git a/vendor/github.com/skip2/go-qrcode/symbol_test.go b/vendor/github.com/skip2/go-qrcode/symbol_test.go new file mode 100644 index 0000000..59b2b6b --- /dev/null +++ b/vendor/github.com/skip2/go-qrcode/symbol_test.go @@ -0,0 +1,334 @@ +// go-qrcode +// Copyright 2014 Tom Harwood + +package qrcode + +import "testing" + +func TestSymbolBasic(t *testing.T) { + size := 10 + quietZoneSize := 4 + + m := newSymbol(size, quietZoneSize) + + if m.size != size+quietZoneSize*2 { + t.Errorf("Symbol size is %d, expected %d", m.size, size+quietZoneSize*2) + } + + for i := 0; i < size; i++ { + for j := 0; j < size; j++ { + + v := m.get(i, j) + + if v != false { + t.Errorf("New symbol not empty") + } + + if !m.empty(i, j) { + t.Errorf("New symbol is not empty") + } + + value := i*j%2 == 0 + m.set(i, j, value) + + v = m.get(i, j) + + if v != value { + t.Errorf("Symbol ignores set bits") + } + + if m.empty(i, j) { + t.Errorf("Symbol ignores set bits") + } + } + } +} + +func TestSymbolPenalties(t *testing.T) { + tests := []struct { + pattern [][]bool + expectedPenalty1 int + expectedPenalty2 int + expectedPenalty3 int + expectedPenalty4 int + }{ + { + [][]bool{ + {b0, b1, b0, b1, b0, b1}, + {b1, b0, b1, b0, b1, b0}, + {b0, b1, b0, b1, b0, b1}, + {b1, b0, b1, b0, b1, b0}, + {b0, b1, b0, b1, b0, b1}, + {b1, b0, b1, b0, b1, b0}, + }, + 0, // No adjacent modules of same color. + 0, // No 2x2+ sized blocks. + 0, // No 1:1:3:1:1 pattern. + -1, + }, + { + [][]bool{ + {b0, b0, b0, b1, b0, b1}, + {b1, b0, b1, b0, b1, b0}, + {b0, b1, b0, b1, b0, b1}, + {b1, b0, b1, b0, b1, b0}, + {b0, b1, b0, b1, b0, b1}, + {b1, b0, b1, b0, b1, b0}, + }, + 0, // 5 adjacent modules of same colour, score = 0. + 0, // No 2x2+ sized blocks. + 0, // No 1:1:3:1:1 pattern. + -1, + }, + { + [][]bool{ + {b0, b0, b0, b0, b0, b0}, + {b1, b0, b1, b0, b1, b0}, + {b0, b1, b0, b1, b0, b1}, + {b1, b0, b1, b0, b1, b0}, + {b0, b1, b0, b1, b0, b1}, + {b1, b0, b1, b0, b1, b0}, + }, + 4, // 6 adjacent modules of same colour, score = 3 + (6-5) + 0, // No 2x2+ sized blocks. + 0, // No 1:1:3:1:1 pattern. + -1, + }, + { + [][]bool{ + {b0, b0, b0, b0, b0, b0, b0}, + {b1, b0, b1, b0, b1, b0, b1}, + {b1, b0, b0, b0, b0, b0, b1}, + {b1, b0, b1, b0, b1, b0, b1}, + {b1, b0, b0, b0, b0, b0, b1}, + {b1, b0, b1, b0, b1, b0, b1}, + {b1, b0, b0, b0, b0, b0, b0}, + }, + 28, // 3+(7-5) + 3+(6-5) + 3+(6-5) + 3+(6-5) + 3+(7-5) + 3+(7-5) = 28 + 0, // No 2x2+ sized blocks. + 0, // No 1:1:3:1:1 pattern. + -1, + }, + { + [][]bool{ + {b0, b0, b0, b1, b0, b1}, + {b0, b0, b1, b0, b1, b0}, + {b0, b1, b0, b1, b0, b1}, + {b1, b0, b1, b1, b1, b0}, + {b0, b1, b1, b1, b0, b1}, + {b1, b0, b1, b0, b1, b0}, + }, + -1, + 6, // 3*(2-1)*(2-1) + 3(2-1)*(2-1) + 0, // No 1:1:3:1:1 pattern. + -1, + }, + { + [][]bool{ + {b0, b0, b0, b0, b0, b1}, + {b0, b0, b0, b0, b0, b1}, + {b0, b0, b0, b0, b0, b1}, + {b0, b0, b0, b0, b0, b1}, + {b0, b0, b0, b0, b0, b1}, + {b0, b0, b0, b0, b0, b1}, + }, + -1, + 60, // 3 * (5-1) * (6-1) + 0, // No 1:1:3:1:1 pattern. + -1, + }, + { + [][]bool{ + {b0, b0, b0, b0, b0, b1}, + {b0, b0, b0, b0, b0, b1}, + {b1, b1, b0, b1, b0, b1}, + {b1, b1, b0, b1, b0, b1}, + {b1, b1, b0, b1, b0, b1}, + {b1, b1, b0, b1, b0, b1}, + }, + -1, + 21, // 3*(5-1)*(2-1) + 3*(2-1)*(4-1) = 3*4 + 3*3 + 0, // No 1:1:3:1:1 pattern. + -1, + }, + { + [][]bool{ + {b0, b0, b0, b0, b1, b0, b1, b1, b1, b0, b1, b0}, + {b0, b0, b0, b0, b1, b0, b1, b1, b1, b0, b1, b0}, + {b0, b0, b0, b0, b1, b0, b1, b1, b1, b0, b1, b0}, + {b0, b0, b0, b0, b1, b0, b1, b1, b1, b0, b1, b0}, + {b0, b0, b0, b0, b1, b0, b1, b1, b1, b0, b1, b0}, + {b0, b0, b0, b0, b1, b0, b1, b1, b1, b0, b1, b0}, + {b0, b0, b0, b0, b1, b0, b1, b1, b1, b0, b1, b0}, + {b0, b0, b0, b0, b1, b0, b1, b1, b1, b0, b1, b0}, + {b0, b0, b0, b0, b1, b0, b1, b1, b1, b0, b1, b0}, + {b0, b0, b0, b0, b1, b0, b1, b1, b1, b0, b1, b0}, + {b0, b0, b0, b0, b1, b0, b1, b1, b1, b0, b1, b0}, + {b0, b0, b0, b0, b1, b0, b1, b1, b1, b0, b1, b0}, + }, + -1, + -1, + 480, // 12* 1:1:3:1:1 patterns, 12 * 40. + -1, + }, + { + [][]bool{ + {b1, b0, b0, b0, b0, b0, b0, b0, b0, b0, b0, b0}, + {b0, b0, b0, b0, b0, b0, b0, b0, b0, b0, b0, b0}, + {b1, b0, b0, b0, b0, b0, b0, b0, b0, b0, b0, b0}, + {b1, b0, b0, b0, b0, b0, b0, b0, b0, b0, b0, b0}, + {b1, b1, b0, b0, b0, b0, b0, b0, b0, b0, b0, b0}, + {b0, b0, b0, b0, b0, b0, b0, b0, b0, b0, b0, b0}, + {b1, b1, b0, b0, b0, b0, b0, b0, b0, b0, b0, b0}, + {b0, b1, b0, b0, b0, b0, b0, b0, b0, b0, b0, b0}, + {b0, b1, b0, b0, b0, b0, b0, b0, b0, b0, b0, b0}, + {b0, b0, b0, b0, b0, b0, b0, b0, b0, b0, b0, b0}, + {b0, b1, b0, b0, b0, b0, b0, b0, b0, b0, b0, b0}, + {b0, b0, b0, b0, b0, b0, b0, b0, b0, b0, b0, b0}, + }, + -1, + -1, + 80, // 2* 1:1:3:1:1 patterns, 2 * 40. + -1, + }, + { + [][]bool{ + {b0, b0, b0, b0, b0, b0, b0, b0, b0, b0}, + {b0, b0, b0, b0, b0, b0, b0, b0, b0, b0}, + {b0, b0, b0, b0, b0, b0, b0, b0, b0, b0}, + {b0, b0, b0, b0, b0, b0, b0, b0, b0, b0}, + {b0, b0, b0, b0, b0, b0, b0, b0, b0, b0}, + {b0, b0, b0, b0, b0, b0, b0, b0, b0, b0}, + {b0, b0, b0, b0, b0, b0, b0, b0, b0, b0}, + {b0, b0, b0, b0, b0, b0, b0, b0, b0, b0}, + {b0, b0, b0, b0, b0, b0, b0, b0, b0, b0}, + {b0, b0, b0, b0, b0, b0, b0, b0, b0, b0}, + }, + -1, + -1, + -1, + 100, // 10 * (10 steps of 5% deviation from 50% black/white). + }, + { + [][]bool{ + {b1, b1, b1, b1, b1, b1, b1, b1, b1, b1}, + {b1, b1, b1, b1, b1, b1, b1, b1, b1, b1}, + {b1, b1, b1, b1, b1, b1, b1, b1, b1, b1}, + {b1, b1, b1, b1, b1, b1, b1, b1, b1, b1}, + {b1, b1, b1, b1, b1, b1, b1, b1, b1, b1}, + {b1, b1, b1, b1, b1, b1, b1, b1, b1, b1}, + {b1, b1, b1, b1, b1, b1, b1, b1, b1, b1}, + {b1, b1, b1, b1, b1, b1, b1, b1, b1, b1}, + {b1, b1, b1, b1, b1, b1, b1, b1, b1, b1}, + {b1, b1, b1, b1, b1, b1, b1, b1, b1, b1}, + }, + -1, + -1, + -1, + 100, // 10 * (10 steps of 5% deviation from 50% black/white). + }, + { + [][]bool{ + {b0, b0, b0, b0, b0, b0, b0, b0, b0, b0}, + {b0, b0, b0, b0, b0, b0, b0, b0, b0, b0}, + {b0, b0, b0, b0, b0, b0, b0, b0, b0, b0}, + {b0, b0, b0, b0, b0, b0, b0, b0, b0, b0}, + {b0, b0, b0, b0, b0, b0, b0, b0, b0, b0}, + {b1, b1, b1, b1, b1, b1, b1, b1, b1, b1}, + {b1, b1, b1, b1, b1, b1, b1, b1, b1, b1}, + {b1, b1, b1, b1, b1, b1, b1, b1, b1, b1}, + {b1, b1, b1, b1, b1, b1, b1, b1, b1, b1}, + {b1, b1, b1, b1, b1, b1, b1, b1, b1, b1}, + }, + -1, + -1, + -1, + 0, // Exactly 50%/50% black/white. + }, + { + [][]bool{ + {b0, b0, b0, b0, b0, b0, b0, b0, b0, b0}, + {b0, b0, b0, b0, b0, b0, b0, b0, b0, b0}, + {b0, b0, b0, b0, b0, b0, b0, b0, b0, b0}, + {b0, b0, b0, b0, b0, b0, b0, b0, b0, b0}, + {b0, b0, b0, b0, b0, b0, b0, b0, b0, b0}, + {b0, b0, b0, b0, b0, b0, b0, b0, b0, b0}, + {b1, b1, b1, b1, b1, b1, b1, b1, b1, b1}, + {b1, b1, b1, b1, b1, b1, b1, b1, b1, b1}, + {b1, b1, b1, b1, b1, b1, b1, b1, b1, b1}, + {b1, b1, b1, b1, b1, b1, b1, b1, b1, b1}, + }, + -1, + -1, + -1, + 20, // 10 * (2 steps of 5% deviation towards white). + }, + { + [][]bool{ + {b0, b0, b0, b0, b0, b0, b0, b0, b0, b0}, + {b0, b0, b0, b0, b0, b0, b0, b0, b0, b0}, + {b0, b0, b0, b0, b0, b0, b0, b0, b0, b0}, + {b0, b0, b0, b0, b0, b0, b0, b0, b0, b0}, + {b0, b0, b0, b0, b0, b0, b0, b0, b0, b0}, + {b0, b0, b0, b0, b0, b0, b0, b0, b0, b0}, + {b0, b0, b0, b0, b0, b0, b1, b1, b1, b1}, + {b1, b1, b1, b1, b1, b1, b1, b1, b1, b1}, + {b1, b1, b1, b1, b1, b1, b1, b1, b1, b1}, + {b1, b1, b1, b1, b1, b1, b1, b1, b1, b1}, + }, + -1, + -1, + -1, + 30, // 10 * (3 steps of 5% deviation towards white). + }, + { + [][]bool{ + {b0, b0, b0, b0, b0, b0, b0, b0, b0, b0}, + {b0, b0, b0, b0, b0, b0, b0, b0, b0, b0}, + {b0, b0, b0, b0, b0, b0, b0, b0, b0, b0}, + {b0, b0, b0, b0, b0, b0, b0, b0, b0, b0}, + {b0, b0, b0, b0, b0, b0, b0, b0, b0, b0}, + {b0, b0, b0, b0, b0, b0, b0, b0, b0, b0}, + {b0, b0, b0, b0, b0, b0, b0, b0, b0, b1}, + {b1, b1, b1, b1, b1, b1, b1, b1, b1, b1}, + {b1, b1, b1, b1, b1, b1, b1, b1, b1, b1}, + {b1, b1, b1, b1, b1, b1, b1, b1, b1, b1}, + }, + -1, + -1, + -1, + 30, // 10 * (3 steps of 5% deviation towards white). + }, + } + + for i, test := range tests { + s := newSymbol(len(test.pattern[0]), 4) + s.set2dPattern(0, 0, test.pattern) + + penalty1 := s.penalty1() + penalty2 := s.penalty2() + penalty3 := s.penalty3() + penalty4 := s.penalty4() + + ok := true + + if test.expectedPenalty1 != -1 && test.expectedPenalty1 != penalty1 { + ok = false + } + if test.expectedPenalty2 != -1 && test.expectedPenalty2 != penalty2 { + ok = false + } + if test.expectedPenalty3 != -1 && test.expectedPenalty3 != penalty3 { + ok = false + } + if test.expectedPenalty4 != -1 && test.expectedPenalty4 != penalty4 { + ok = false + } + + if !ok { + t.Fatalf("Penalty test #%d p1=%d, p2=%d, p3=%d, p4=%d (expected p1=%d, p2=%d, p3=%d, p4=%d)", i, penalty1, penalty2, penalty3, penalty4, + test.expectedPenalty1, test.expectedPenalty2, test.expectedPenalty3, + test.expectedPenalty4) + } + } +} diff --git a/vendor/github.com/skip2/go-qrcode/version_test.go b/vendor/github.com/skip2/go-qrcode/version_test.go new file mode 100644 index 0000000..5640226 --- /dev/null +++ b/vendor/github.com/skip2/go-qrcode/version_test.go @@ -0,0 +1,158 @@ +// go-qrcode +// Copyright 2014 Tom Harwood + +package qrcode + +import ( + "testing" + + bitset "github.com/skip2/go-qrcode/bitset" +) + +func TestFormatInfo(t *testing.T) { + tests := []struct { + level RecoveryLevel + maskPattern int + + expected uint32 + }{ + { // L=01 M=00 Q=11 H=10 + Low, + 1, + 0x72f3, + }, + { + Medium, + 2, + 0x5e7c, + }, + { + High, + 3, + 0x3a06, + }, + { + Highest, + 4, + 0x0762, + }, + { + Low, + 5, + 0x6318, + }, + { + Medium, + 6, + 0x4f97, + }, + { + High, + 7, + 0x2bed, + }, + } + + for i, test := range tests { + v := getQRCodeVersion(test.level, 1) + + result := v.formatInfo(test.maskPattern) + + expected := bitset.New() + expected.AppendUint32(test.expected, formatInfoLengthBits) + + if !expected.Equals(result) { + t.Errorf("formatInfo test #%d got %s, expected %s", i, result.String(), + expected.String()) + } + } +} + +func TestVersionInfo(t *testing.T) { + tests := []struct { + version int + expected uint32 + }{ + { + 7, + 0x007c94, + }, + { + 10, + 0x00a4d3, + }, + { + 20, + 0x0149a6, + }, + { + 30, + 0x01ed75, + }, + { + 40, + 0x028c69, + }, + } + + for i, test := range tests { + var v *qrCodeVersion + + v = getQRCodeVersion(Low, test.version) + + result := v.versionInfo() + + expected := bitset.New() + expected.AppendUint32(test.expected, versionInfoLengthBits) + + if !expected.Equals(result) { + t.Errorf("versionInfo test #%d got %s, expected %s", i, result.String(), + expected.String()) + } + } +} + +func TestNumBitsToPadToCodeoword(t *testing.T) { + tests := []struct { + level RecoveryLevel + version int + + numDataBits int + expected int + }{ + { + Low, + 1, + 0, + 0, + }, { + Low, + 1, + 1, + 7, + }, { + Low, + 1, + 7, + 1, + }, { + Low, + 1, + 8, + 0, + }, + } + + for i, test := range tests { + var v *qrCodeVersion + + v = getQRCodeVersion(test.level, test.version) + + result := v.numBitsToPadToCodeword(test.numDataBits) + + if result != test.expected { + t.Errorf("numBitsToPadToCodeword test %d (version=%d numDataBits=%d), got %d, expected %d", + i, test.version, test.numDataBits, result, test.expected) + } + } +} |
