// Copyright (c) 2026 Petr BalvĂ­n (https://petrbalvin.org) // SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0 package qrcode import ( "os/exec" "strings" "testing" ) // reference renders the same symbol with the system qrencode and // returns its module matrix, or skips the test when the tool is absent. func reference(t *testing.T, text string) [][]bool { t.Helper() binary, err := exec.LookPath("qrencode") if err != nil { t.Skip("qrencode is not installed; the differential test cannot run") } out, err := exec.Command(binary, "-l", "M", "-m", "0", "--type=ASCII", text).Output() if err != nil { t.Fatalf("qrencode: %v", err) } var rows [][]bool for line := range strings.SplitSeq(string(out), "\n") { line = strings.TrimSuffix(line, "\r") if line == "" { continue } // A row may be entirely light modules, which trims to spaces: // only a truly empty line separates rows, so nothing is dropped. if len(line)%2 != 0 { t.Fatalf("odd ASCII line %q", line) } row := make([]bool, len(line)/2) for i := range row { row[i] = line[i*2] == '#' } rows = append(rows, row) } return rows } // referenceMask decodes the mask the reference chose from its own // format information, using the layout this package writes. func referenceMask(t *testing.T, ref [][]bool) int { t.Helper() var word uint cells := func(y, x int) uint { if ref[y][x] { return 1 } return 0 } for i := range 6 { word = word<<1 | cells(8, i) } word = word<<1 | cells(8, 7) word = word<<1 | cells(8, 8) word = word<<1 | cells(7, 8) for i := range 6 { word = word<<1 | cells(5-i, 8) } // The stored word carries the XOR mask; the data sits on top once // it is undone. return int((word^0x5412)>>10) & 7 } func diffMatrices(t *testing.T, text string) { t.Helper() // The reference's own mask, forced: every other bit of the symbol // must then match, which proves the encoding, the error correction, // the placement and the format information. The mask each encoder // picks for itself is a choice among equally valid symbols. theirs := reference(t, text) mask := referenceMask(t, theirs) ours, err := encodeMasked([]byte(text), mask) if err != nil { t.Fatalf("encode %q: %v", text, err) } if len(theirs) != len(ours) { t.Fatalf("%q: size %d, reference %d", text, len(ours), len(theirs)) } for y := range ours { for x := range ours[y] { if ours[y][x] != theirs[y][x] { t.Fatalf("%q: module differs at (%d,%d)", text, x, y) } } } } // TestAgainstQrencode is the proof of the encoder: for the full range // of payloads, every module must match the reference implementation // once its own mask is forced. The payloads stay clear of the // reference's segmentation optimiser: letters and underscores carry no // alphanumeric runs worth switching for, so it speaks plain byte mode // the way this package always does. func TestAgainstQrencode(t *testing.T) { payloads := []string{ "hello world", "otpauth_totp_volumen_petr_secret_and_issuer_example_uri", "https_petrbalvin_org_neco_delsi_cesta_query_hodnota_druha_ano", strings.Repeat("a", 14), // v1 edge strings.Repeat("a", 15), // v2 strings.Repeat("b", 84), // v5 edge strings.Repeat("b", 85), // v6 strings.Repeat("c", 180), // v9 edge strings.Repeat("c", 181), // v10 (16-bit count) strings.Repeat("d", 450), // v16 edge } for i := range 10 { payloads = append(payloads, strings.Repeat("x", 1+i*45)) } for _, p := range payloads { diffMatrices(t, p) } } func TestSVGShape(t *testing.T) { svg, err := SVG("https://example.com/") if err != nil { t.Fatalf("SVG: %v", err) } for _, want := range []string{ `viewBox="0 0 33 33"`, // v1 + quiet zone ``, `fill="#000"`, ``, } { if !strings.Contains(svg, want) { t.Fatalf("missing %q in %s", want, svg[:min(len(svg), 200)]) } } } func TestTooLongIsRefused(t *testing.T) { if _, err := SVG(strings.Repeat("z", 450)); err != nil { t.Fatalf("version 16 capacity refused: %v", err) } if _, err := SVG(strings.Repeat("z", 451)); err == nil { t.Fatal("input beyond version 16 accepted") } }