/* * govis: unicode aware vis(3) encoding implementation * Copyright (C) 2017 SUSE LLC. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package govis import ( "bytes" "crypto/rand" "testing" ) const DefaultVisFlags = VisWhite | VisOctal | VisGlob func TestRandomVisUnvis(t *testing.T) { // Randomly generate N strings. const N = 100 for i := 0; i < N; i++ { testBytes := make([]byte, 256) if n, err := rand.Read(testBytes); n != cap(testBytes) || err != nil { t.Fatalf("could not read enough bytes: err=%v n=%d", err, n) } test := string(testBytes) for flag := VisFlag(0); flag <= visMask; flag++ { // VisNoSlash is frankly just a dumb flag, and it is impossible for us // to actually preserve things in a round-trip. if flag&VisNoSlash == VisNoSlash { continue } enc, err := Vis(test, flag) if err != nil { t.Errorf("unexpected error doing vis(%q, %b): %s", test, flag, err) continue } dec, err := Unvis(enc, flag) if err != nil { t.Errorf("unexpected error doing unvis(%q, %b): %s", enc, flag, err) continue } if dec != test { t.Errorf("roundtrip failed: unvis(vis(%q, %b) = %q, %b) = %q", test, flag, enc, flag, dec) } } } } func TestRandomVisVisUnvisUnvis(t *testing.T) { // Randomly generate N strings. const N = 100 for i := 0; i < N; i++ { testBytes := make([]byte, 256) if n, err := rand.Read(testBytes); n != cap(testBytes) || err != nil { t.Fatalf("could not read enough bytes: err=%v n=%d", err, n) } test := string(testBytes) for flag := VisFlag(0); flag <= visMask; flag++ { // VisNoSlash is frankly just a dumb flag, and it is impossible for us // to actually preserve things in a round-trip. if flag&VisNoSlash == VisNoSlash { continue } enc, err := Vis(test, flag) if err != nil { t.Errorf("unexpected error doing vis(%q, %b): %s", test, flag, err) continue } enc2, err := Vis(enc, flag) if err != nil { t.Errorf("unexpected error doing vis(%q, %b): %s", enc, flag, err) continue } dec, err := Unvis(enc2, flag) if err != nil { t.Errorf("unexpected error doing unvis(%q, %b): %s", enc2, flag, err) continue } dec2, err := Unvis(dec, flag) if err != nil { t.Errorf("unexpected error doing unvis(%q, %b): %s", dec, flag, err) continue } if dec2 != test { t.Errorf("roundtrip failed: unvis(unvis(vis(vis(%q) = %q) = %q) = %q, %b) = %q", test, enc, enc2, dec, flag, dec2) } } } } func TestVisUnvis(t *testing.T) { for flag := VisFlag(0); flag <= visMask; flag++ { // VisNoSlash is frankly just a dumb flag, and it is impossible for us // to actually preserve things in a round-trip. if flag&VisNoSlash == VisNoSlash { continue } // Round-trip testing. for _, test := range []string{ "", "hello world", "THIS\\IS_A_TEST1234", "this.is.a.normal_string", "AC_Ra\u00edz_Certic\u00e1mara_S.A..pem", "NetLock_Arany_=Class_Gold=_F\u0151tan\u00fas\u00edtv\u00e1ny.pem", "T\u00dcB\u0130TAK_UEKAE_K\u00f6k_Sertifika_Hizmet_Sa\u011flay\u0131c\u0131s\u0131_-_S\u00fcr\u00fcm_3.pem", "hello world [ this string needs=enco ding! ]", "even \n more encoding necessary\a\a ", "\024 <-- some more weird characters --> \u4f60\u597d\uff0c\u4e16\u754c", "\\xff\\n double encoding is also great fun \\x", "AC_Ra\\M-C\\M--z_Certic\\M-C\\M-!mara_S.A..pem", "z^i3i$\u00d3\u008anqgh5/t\u00e5<86>\u00b2kzla\\e^lv\u00df\u0093nv\u00df\u00aea|3}\u00d8\u0088\u00d6\u0084", `z^i3i$\M-C\M^S\M-B\M^Jnqgh5/t\M-C\M-%<86>\M-B\M-2kzla\\e^lv\M-C\M^_\M-B\M^Snv\M-C\M^_\M-B\M-.a|3}\M-C\M^X\M-B\M^H\M-C\M^V\M-B\M^D`, "@?e1xs+.R_Kjo]7s8pgRP:*nXCE4{!c", "62_\u00c6\u00c62\u00ae\u00b7m\u00db\u00c3r^\u00bfp\u00c6u'q\u00fbc2\u00f0u\u00b8\u00dd\u00e8v\u00ff\u00b0\u00dc\u00c2\u00f53\u00db-k\u00f2sd4\\p\u00da\u00a6\u00d3\u00eea<\u00e6s{\u00a0p\u00f0\u00ffj\u00e0\u00e8\u00b8\u00b8\u00bc\u00fcb", `62_\M-C\M^F\M-C\M^F2\M-B\M-.\M-B\M-7m\M-C\M^[\M-C\M^Cr^\M-B\M-?p\M-C\M^Fu'q\M-C\M-;c2\M-C\M-0u\M-B\M-8\M-C\M^]\M-C\M-(v\M-C\M-?\M-B\M-0\M-C\M^\\M-C\M^B\M-C\M-53\M-C\M^[-k\M-C\M-2sd4\\p\M-C\M^Z\M-B\M-&\M-C\M^S\M-C\M-.a<\M-C\M-&s{\M-B\240p\M-C\M-0\M-C\M-?j\M-C\240\M-C\M-(\M-B\M-8\M-B\M-8\M-B\M-<\M-C\M-<b`, "\u9003\"9v1)T798|o;fly jnKX\u0489Be=", `\M-i\M^@\M^C"9v1)T798|o;fly jnKX\M-R\M^IBe=`, "'3Ze\u050e|\u02del\u069du-Rpct4+Z5b={@_{b", `'3Ze\M-T\M^N|\M-K\M^^l\M-Z\M^]u-Rpct4+Z5b={@_{b`, "1\u00c6\u00abTcz+Vda?)k1%\\\"P;`po`h", `1%C3%86%C2%ABTcz+Vda%3F)k1%25%5C%22P%3B%60po%60h`, } { enc, err := Vis(test, flag) if err != nil { t.Errorf("unexpected error doing vis(%q, %b): %s", test, flag, err) continue } dec, err := Unvis(enc, flag) if err != nil { t.Errorf("unexpected error doing unvis(%q, %b): %s", enc, flag, err) continue } if dec != test { t.Errorf("roundtrip failed: unvis(vis(%q, %b) = %q, %b) = %q", test, flag, enc, flag, dec) } } } } func TestByteStrings(t *testing.T) { // It's important to make sure that we don't mess around with the layout of // bytes when doing a round-trip. Otherwise we risk outputting visually // identical but bit-stream non-identical strings (causing much confusion // when trying to access such files). for _, test := range [][]byte{ []byte("This is a man in business suit levitating: \U0001f574"), {0x7f, 0x17, 0x01, 0x33}, // TODO: Test arbitrary byte streams like the one below. Currently this // fails because Vis() is messing around with it (converting it // to a rune and spacing it out). //{'\xef', '\xae', 'h', '\077', 'k'}, } { testString := string(test) enc, err := Vis(testString, DefaultVisFlags) if err != nil { t.Errorf("unexpected error doing vis(%q): %s", test, err) continue } dec, err := Unvis(enc, DefaultVisFlags) if err != nil { t.Errorf("unexpected error doing unvis(%q): %s", enc, err) continue } decBytes := []byte(dec) if dec != testString { t.Errorf("roundtrip failed [string comparison]: unvis(vis(%q) = %q) = %q", test, enc, dec) } if !bytes.Equal(decBytes, test) { t.Errorf("roundtrip failed [byte comparison]: unvis(vis(%q) = %q) = %q", test, enc, dec) } } }