package asciisanitizer import ( "bytes" "testing" "testing/iotest" "github.com/stretchr/testify/require" "golang.org/x/text/transform" ) func TestSanitizerTransform(t *testing.T) { tests := []struct { name string json bool input string want string }{ { name: "No control characters", input: "The quick brown fox jumped over the lazy dog", want: "The quick brown fox jumped over the lazy dog", }, { name: "JSON sanitization maintains valid JSON", json: true, input: `\u001B \\u001B \\\u001B \\\\u001B \\u001B\\u001B`, want: `^[ \\^[ \\^[ \\\\^[ \\^[\\^[`, }, { name: "JSON C0 control character", json: true, input: `0\u0000`, want: "0^@", }, { name: "JSON C0 control characters", json: true, input: `0\u0000 1\u0001 2\u0002 3\u0003 4\u0004 5\u0005 6\u0006 7\u0007 8\u0008 9\u0009 ` + `A\u000a B\u000b C\u000c D\u000d E\u000e F\u000f ` + `10\u0010 11\u0011 12\u0012 13\u0013 14\u0014 15\u0015 16\u0016 17\u0017 18\u0018 19\u0019 ` + `1A\u001a 1B\u001b 1C\u001c 1D\u001d 1E\u001e 1F\u001f`, want: `0^@ 1^A 2^B 3^C 4^D 5^E 6^F 7^G 8^H 9\u0009 ` + `A\u000a B\u000b C^L D\u000d E^N F^O ` + `10^P 11^Q 12^R 13^S 14^T 15^U 16^V 17^W 18^X 19^Y ` + `1A^Z 1B^[ 1C^\\ 1D^] 1E^^ 1F^_`, }, { name: "JSON C1 control characters", json: true, input: `80\u0080 81\u0081 82\u0082 83\u0083 84\u0084 85\u0085 86\u0086 87\u0087 88\u0088 89\u0089 ` + `8A\u008a 8B\u008b 8C\u008c 8D\u008d 8E\u008e 8F\u008f ` + `90\u0090 91\u0091 92\u0092 93\u0093 94\u0094 95\u0095 96\u0096 97\u0097 98\u0098 99\u0099 ` + `9A\u009a 9B\u009b 9C\u009c 9D\u009d 9E\u009e 9F\u009f`, want: `80^@ 81^A 82^B 83^C 84^D 85^E 86^F 87^G 88^H 89^I ` + `8A^J 8B^K 8C^L 8D^M 8E^N 8F^O ` + `90^P 91^Q 92^R 93^S 94^T 95^U 96^V 97^W 98^X 99^Y ` + `9A^Z 9B^[ 9C^\\ 9D^] 9E^^ 9F^_`, }, { name: "C0 control character", input: "0\x00", want: "0^@", }, { name: "C0 control characters", input: "0\x00 1\x01 2\x02 3\x03 4\x04 5\x05 6\x06 7\x07 8\x08 9\x09 " + "A\x0A B\x0B C\x0C D\x0D E\x0E F\x0F " + "10\x10 11\x11 12\x12 13\x13 14\x14 15\x15 16\x16 17\x17 18\x18 19\x19 " + "1A\x1A 1B\x1B 1C\x1C 1D\x1D 1E\x1E 1F\x1F", want: "0^@ 1^A 2^B 3^C 4^D 5^E 6^F 7^G 8^H 9\t " + "A\n B\v C^L D\r E^N F^O " + "10^P 11^Q 12^R 13^S 14^T 15^U 16^V 17^W 18^X 19^Y " + "1A^Z 1B^[ 1C^\\\\ 1D^] 1E^^ 1F^_", }, { name: "C1 control character", input: "80\xC2\x80", want: "80^@", }, { name: "C1 control characters", input: "80\xC2\x80 81\xC2\x81 82\xC2\x82 83\xC2\x83 84\xC2\x84 85\xC2\x85 86\xC2\x86 87\xC2\x87 88\xC2\x88 89\xC2\x89 " + "8A\xC2\x8A 8B\xC2\x8B 8C\xC2\x8C 8D\xC2\x8D 8E\xC2\x8E 8F\xC2\x8F " + "90\xC2\x90 91\xC2\x91 92\xC2\x92 93\xC2\x93 94\xC2\x94 95\xC2\x95 96\xC2\x96 97\xC2\x97 98\xC2\x98 99\xC2\x99 " + "9A\xC2\x9A 9B\xC2\x9B 9C\xC2\x9C 9D\xC2\x9D 9E\xC2\x9E 9F\xC2\x9F", want: "80^@ 81^A 82^B 83^C 84^D 85^E 86^F 87^G 88^H 89^I " + "8A^J 8B^K 8C^L 8D^M 8E^N 8F^O " + "90^P 91^Q 92^R 93^S 94^T 95^U 96^V 97^W 98^X 99^Y " + "9A^Z 9B^[ 9C^\\\\ 9D^] 9E^^ 9F^_", }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { sanitizer := &Sanitizer{JSON: tt.json} reader := bytes.NewReader([]byte(tt.input)) transformReader := transform.NewReader(reader, sanitizer) err := iotest.TestReader(transformReader, []byte(tt.want)) require.NoError(t, err) }) } }