github.com/Psiphon-Labs/psiphon-tunnel-core@v2.0.28+incompatible/psiphon/common/transforms/transforms_test.go (about) 1 /* 2 * Copyright (c) 2022, Psiphon Inc. 3 * All rights reserved. 4 * 5 * This program is free software: you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License as published by 7 * the Free Software Foundation, either version 3 of the License, or 8 * (at your option) any later version. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License 16 * along with this program. If not, see <http://www.gnu.org/licenses/>. 17 * 18 */ 19 20 package transforms 21 22 import ( 23 "reflect" 24 "strings" 25 "testing" 26 27 "github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/errors" 28 "github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/prng" 29 ) 30 31 func TestTransforms(t *testing.T) { 32 err := runTestTransforms() 33 if err != nil { 34 t.Fatalf(errors.Trace(err).Error()) 35 } 36 } 37 38 func runTestTransforms() error { 39 40 transformNameAny := "exampleTransform1" 41 transformNameScoped := "exampleTransform2" 42 scopeName := "exampleScope" 43 44 specs := Specs{ 45 transformNameAny: Spec{[2]string{"x", "y"}}, 46 transformNameScoped: Spec{ 47 [2]string{"aa", "cc"}, 48 [2]string{"bb", "(dd|ee)"}, 49 [2]string{"^([c0]{6})", "\\$\\{1\\}ff0"}, 50 }, 51 } 52 53 scopedSpecs := ScopedSpecNames{ 54 SCOPE_ANY: []string{transformNameAny}, 55 scopeName: []string{transformNameScoped}, 56 } 57 58 // Test: validation 59 60 err := specs.Validate() 61 if err != nil { 62 return errors.Trace(err) 63 } 64 65 err = scopedSpecs.Validate(specs) 66 if err != nil { 67 return errors.Trace(err) 68 } 69 70 // Test: select based on scope 71 72 name, spec := specs.Select(SCOPE_ANY, scopedSpecs) 73 if name != transformNameAny || !reflect.DeepEqual(spec, specs[transformNameAny]) { 74 return errors.TraceNew("unexpected select result") 75 } 76 77 name, spec = specs.Select(scopeName, scopedSpecs) 78 if name != transformNameScoped || !reflect.DeepEqual(spec, specs[transformNameScoped]) { 79 return errors.TraceNew("unexpected select result") 80 } 81 82 // Test: correct transform (assumes spec is transformNameScoped) 83 84 seed, err := prng.NewSeed() 85 if err != nil { 86 return errors.Trace(err) 87 } 88 89 input := "aa0aa0aa0bb0aa0bb0aa0bb0aa0bb0aa0bb0aa0bb0aa0bb0aa0bb0aa0bb0aa" 90 output, err := spec.Apply(seed, input) 91 if err != nil { 92 return errors.Trace(err) 93 } 94 95 if !strings.HasPrefix(output, "cc0cc0ff0") || 96 strings.IndexAny(output, "ab") != -1 || 97 strings.IndexAny(output, "de") == -1 { 98 return errors.Tracef("unexpected apply result: %s", output) 99 } 100 101 // Test: same result with same seed 102 103 previousOutput := output 104 105 output, err = spec.Apply(seed, input) 106 if err != nil { 107 return errors.Trace(err) 108 } 109 110 if output != previousOutput { 111 return errors.Tracef("unexpected different apply result") 112 } 113 114 // Test: different result with different seed (with high probability) 115 116 different := false 117 for i := 0; i < 1000; i++ { 118 119 seed, err = prng.NewSeed() 120 if err != nil { 121 return errors.Trace(err) 122 } 123 124 output, err = spec.Apply(seed, input) 125 if err != nil { 126 return errors.Trace(err) 127 } 128 129 if output != previousOutput { 130 different = true 131 break 132 } 133 } 134 135 if !different { 136 return errors.Tracef("unexpected identical apply result") 137 } 138 139 return nil 140 }