packed_test.go 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  1. /*
  2. * Copyright (c) 2023, 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. package protocol
  20. import (
  21. "encoding/base64"
  22. "encoding/json"
  23. "fmt"
  24. "reflect"
  25. "strings"
  26. "testing"
  27. "time"
  28. "github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common"
  29. "github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/accesscontrol"
  30. "github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/prng"
  31. )
  32. func TestPackedAPIParameters(t *testing.T) {
  33. params := make(common.APIParameters)
  34. for name, spec := range packedAPIParametersNameToSpec {
  35. params[name] = makeTestPackValue(t, spec)
  36. }
  37. packedParams, err := EncodePackedAPIParameters(params)
  38. if err != nil {
  39. t.Fatalf("EncodePackedAPIParameters failed: %v", err)
  40. }
  41. unpackedParams, err := DecodePackedAPIParameters(packedParams)
  42. if err != nil {
  43. t.Fatalf("DecodePackedAPIParameters failed: %v", err)
  44. }
  45. checkTestPackValues(
  46. t, packedAPIParametersNameToSpec, params, unpackedParams)
  47. }
  48. func TestPackedServerEntry(t *testing.T) {
  49. fields := make(ServerEntryFields)
  50. for name, spec := range packedServerEntryFieldsNameToSpec {
  51. fields[name] = makeTestPackValue(t, spec)
  52. }
  53. unrecognized := "unrecognized_field_name"
  54. fields[unrecognized] = prng.HexString(prng.Range(1, 1000))
  55. packedFields, err := EncodePackedServerEntryFields(fields)
  56. if err != nil {
  57. t.Fatalf("EncodePackedServerEntryFields failed: %v", err)
  58. }
  59. unpackedFields, err := DecodePackedServerEntryFields(packedFields)
  60. if err != nil {
  61. t.Fatalf("DecodePackedServerEntryFields failed: %v", err)
  62. }
  63. checkTestPackValues(
  64. t, packedServerEntryFieldsNameToSpec, fields, unpackedFields)
  65. if !reflect.DeepEqual(fields[unrecognized], unpackedFields[unrecognized]) {
  66. t.Errorf("decoded value %s not equal: %T %+v != %T %+v",
  67. unrecognized,
  68. fields[unrecognized], fields[unrecognized],
  69. unpackedFields[unrecognized], unpackedFields[unrecognized])
  70. }
  71. }
  72. func makeTestPackValue(t *testing.T, spec packSpec) interface{} {
  73. switch spec.converter {
  74. case nil:
  75. return prng.HexString(prng.Range(1, 1000))
  76. case intConverter:
  77. return fmt.Sprintf("%d", prng.Intn(1>>32))
  78. case floatConverter:
  79. return fmt.Sprintf("%f", float64(prng.Intn(1>>32)))
  80. case lowerHexConverter:
  81. return prng.HexString(prng.Range(1, 1000))
  82. case upperHexConverter:
  83. return strings.ToUpper(prng.HexString((prng.Range(1, 1000))))
  84. case base64Converter:
  85. return base64.StdEncoding.EncodeToString(prng.Bytes(prng.Range(1, 1000)))
  86. case unpaddedBase64Converter:
  87. return base64.RawStdEncoding.EncodeToString(prng.Bytes(prng.Range(1, 1000)))
  88. case authorizationsConverter:
  89. signingKey, _, err0 := accesscontrol.NewKeyPair("test-access-type")
  90. auth1, _, err1 := accesscontrol.IssueAuthorization(signingKey, []byte("1"), time.Now().Add(1*time.Second))
  91. auth2, _, err2 := accesscontrol.IssueAuthorization(signingKey, []byte("2"), time.Now().Add(1*time.Second))
  92. if err0 != nil || err1 != nil || err2 != nil {
  93. t.Fatalf("accesscontrol.NewKeyPair/IssueAuthorization failed")
  94. }
  95. return []string{auth1, auth2}
  96. case rawJSONConverter:
  97. return []byte(fmt.Sprintf(`{"A":%d, "B":%d}`, prng.Intn(1>>32), prng.Intn(1>>32)))
  98. case compatibleJSONMapConverter:
  99. return []any{map[any]any{"a": 1, "b": 2}, map[any]any{"a": 3, "b": 4}}
  100. }
  101. t.Fatalf("unexpected converter")
  102. return nil
  103. }
  104. func checkTestPackValues(
  105. t *testing.T,
  106. specs map[string]packSpec,
  107. originalValues map[string]interface{},
  108. unpackedValues map[string]interface{}) {
  109. for name, spec := range specs {
  110. originalValue := originalValues[name]
  111. unpackedValue := unpackedValues[name]
  112. if spec.converter == rawJSONConverter {
  113. // Special case: for rawJSONConverter, the input is bytes while
  114. // the output is unmarshaled JSON.
  115. var unmarshaledJSON map[string]interface{}
  116. _ = json.Unmarshal(originalValue.([]byte), &unmarshaledJSON)
  117. originalValue = unmarshaledJSON
  118. } else if spec.converter == compatibleJSONMapConverter {
  119. // Special case: for compatibleJSONMapConverter, reverse the
  120. // conversion to produce the original value with the same type.
  121. unpackedSlice, ok := unpackedValue.([]map[string]interface{})
  122. if !ok {
  123. t.Errorf("expected []map[string]interface {} type")
  124. return
  125. }
  126. entries := make([]interface{}, len(unpackedSlice))
  127. for i, unpackedEntry := range unpackedSlice {
  128. entry := make(map[interface{}]interface{})
  129. for key, value := range unpackedEntry {
  130. entry[key] = value
  131. }
  132. entries[i] = entry
  133. }
  134. unpackedValue = entries
  135. }
  136. if !reflect.DeepEqual(originalValue, unpackedValue) {
  137. t.Errorf("decoded value %s not equal: %T %+v != %T %+v",
  138. name, originalValue, originalValue, unpackedValue, unpackedValue)
  139. }
  140. }
  141. }