git.sr.ht/~pingoo/stdx@v0.0.0-20240218134121-094174641f6e/barcode/aztec/highlevel_test.go (about)

     1  package aztec
     2  
     3  import (
     4  	"bytes"
     5  	"strings"
     6  	"testing"
     7  
     8  	"git.sr.ht/~pingoo/stdx/barcode/utils"
     9  )
    10  
    11  func bitStr(bl *utils.BitList) string {
    12  	buf := new(bytes.Buffer)
    13  
    14  	for i := 0; i < bl.Len(); i++ {
    15  		if bl.GetBit(i) {
    16  			buf.WriteRune('X')
    17  		} else {
    18  			buf.WriteRune('.')
    19  		}
    20  	}
    21  	return buf.String()
    22  }
    23  
    24  func testHighLevelEncodeString(t *testing.T, s, expectedBits string) {
    25  	bits := highlevelEncode([]byte(s))
    26  	result := bitStr(bits)
    27  	expectedBits = strings.Replace(expectedBits, " ", "", -1)
    28  
    29  	if result != expectedBits {
    30  		t.Errorf("invalid result for highlevelEncode(%q). Got:\n%s", s, result)
    31  	}
    32  }
    33  func testHighLevelEncodeStringCnt(t *testing.T, s string, expectedBitCnt int) {
    34  	bits := highlevelEncode([]byte(s))
    35  
    36  	if bits.Len() != expectedBitCnt {
    37  		t.Errorf("invalid result for highlevelEncode(%q). Got %d, expected %d bits", s, bits.Len(), expectedBitCnt)
    38  	}
    39  }
    40  
    41  func Test_HighLevelEncode(t *testing.T) {
    42  	testHighLevelEncodeString(t, "A. b.",
    43  		// 'A'  P/S   '. ' L/L    b    D/L    '.'
    44  		"...X. ..... ...XX XXX.. ...XX XXXX. XX.X")
    45  	testHighLevelEncodeString(t, "Lorem ipsum.",
    46  		// 'L'  L/L   'o'   'r'   'e'   'm'   ' '   'i'   'p'   's'   'u'   'm'   D/L   '.'
    47  		".XX.X XXX.. X.... X..XX ..XX. .XXX. ....X .X.X. X...X X.X.. X.XX. .XXX. XXXX. XX.X")
    48  	testHighLevelEncodeString(t, "Lo. Test 123.",
    49  		// 'L'  L/L   'o'   P/S   '. '  U/S   'T'   'e'   's'   't'    D/L   ' '  '1'  '2'  '3'  '.'
    50  		".XX.X XXX.. X.... ..... ...XX XXX.. X.X.X ..XX. X.X.. X.X.X  XXXX. ...X ..XX .X.. .X.X XX.X")
    51  	testHighLevelEncodeString(t, "Lo...x",
    52  		// 'L'  L/L   'o'   D/L   '.'  '.'  '.'  U/L  L/L   'x'
    53  		".XX.X XXX.. X.... XXXX. XX.X XX.X XX.X XXX. XXX.. XX..X")
    54  	testHighLevelEncodeString(t, ". x://abc/.",
    55  		//P/S   '. '  L/L   'x'   P/S   ':'   P/S   '/'   P/S   '/'   'a'   'b'   'c'   P/S   '/'   D/L   '.'
    56  		"..... ...XX XXX.. XX..X ..... X.X.X ..... X.X.. ..... X.X.. ...X. ...XX ..X.. ..... X.X.. XXXX. XX.X")
    57  	// Uses Binary/Shift rather than Lower/Shift to save two bits.
    58  	testHighLevelEncodeString(t, "ABCdEFG",
    59  		//'A'   'B'   'C'   B/S    =1    'd'     'E'   'F'   'G'
    60  		"...X. ...XX ..X.. XXXXX ....X .XX..X.. ..XX. ..XXX .X...")
    61  
    62  	testHighLevelEncodeStringCnt(t,
    63  		// Found on an airline boarding pass.  Several stretches of Binary shift are
    64  		// necessary to keep the bitcount so low.
    65  		"09  UAG    ^160MEUCIQC0sYS/HpKxnBELR1uB85R20OoqqwFGa0q2uEi"+
    66  			"Ygh6utAIgLl1aBVM4EOTQtMQQYH9M2Z3Dp4qnA/fwWuQ+M8L3V8U=",
    67  		823)
    68  }
    69  
    70  func Test_HighLevelEncodeBinary(t *testing.T) {
    71  	// binary short form single byte
    72  	testHighLevelEncodeString(t, "N\u0000N",
    73  		// 'N'  B/S    =1   '\0'      N
    74  		".XXXX XXXXX ....X ........ .XXXX") // Encode "N" in UPPER
    75  
    76  	testHighLevelEncodeString(t, "N\u0000n",
    77  		// 'N'  B/S    =2   '\0'       'n'
    78  		".XXXX XXXXX ...X. ........ .XX.XXX.") // Encode "n" in BINARY
    79  
    80  	// binary short form consecutive bytes
    81  	testHighLevelEncodeString(t, "N\x00\x80 A",
    82  		// 'N'  B/S    =2    '\0'    \u0080   ' '  'A'
    83  		".XXXX XXXXX ...X. ........ X....... ....X ...X.")
    84  
    85  	// binary skipping over single character
    86  	testHighLevelEncodeString(t, "\x00a\xFF\x80 A",
    87  		// B/S  =4    '\0'      'a'     '\3ff'   '\200'   ' '   'A'
    88  		"XXXXX ..X.. ........ .XX....X XXXXXXXX X....... ....X ...X.")
    89  
    90  	// getting into binary mode from digit mode
    91  	testHighLevelEncodeString(t, "1234\u0000",
    92  		//D/L   '1'  '2'  '3'  '4'  U/L  B/S    =1    \0
    93  		"XXXX. ..XX .X.. .X.X .XX. XXX. XXXXX ....X ........")
    94  
    95  	// Create a string in which every character requires binary
    96  	sb := new(bytes.Buffer)
    97  	for i := 0; i <= 3000; i++ {
    98  		sb.WriteByte(byte(128 + (i % 30)))
    99  	}
   100  
   101  	// Test the output generated by Binary/Switch, particularly near the
   102  	// places where the encoding changes: 31, 62, and 2047+31=2078
   103  	for _, i := range []int{1, 2, 3, 10, 29, 30, 31, 32, 33, 60, 61, 62, 63, 64, 2076, 2077, 2078, 2079, 2080, 2100} {
   104  		// This is the expected length of a binary string of length "i"
   105  		expectedLength := (8 * i)
   106  		switch {
   107  		case i <= 31:
   108  			expectedLength += 10
   109  		case i <= 62:
   110  			expectedLength += 20
   111  		case i <= 2078:
   112  			expectedLength += 21
   113  		default:
   114  			expectedLength += 31
   115  		}
   116  		data := string(sb.Bytes()[:i])
   117  
   118  		// Verify that we are correct about the length.
   119  		testHighLevelEncodeStringCnt(t, data, expectedLength)
   120  		if i != 1 && i != 32 && i != 2079 {
   121  			// The addition of an 'a' at the beginning or end gets merged into the binary code
   122  			// in those cases where adding another binary character only adds 8 or 9 bits to the result.
   123  			// So we exclude the border cases i=1,32,2079
   124  			// A lower case letter at the beginning will be merged into binary mode
   125  			testHighLevelEncodeStringCnt(t, "a"+string(sb.Bytes()[:i-1]), expectedLength)
   126  			// A lower case letter at the end will also be merged into binary mode
   127  			testHighLevelEncodeStringCnt(t, string(sb.Bytes()[:i-1])+"a", expectedLength)
   128  		}
   129  		// A lower case letter at both ends will enough to latch us into LOWER.
   130  		testHighLevelEncodeStringCnt(t, "a"+data+"b", expectedLength+15)
   131  	}
   132  }