size_test.go 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  1. // Copyright (C) 2017 The Syncthing Authors.
  2. //
  3. // This Source Code Form is subject to the terms of the Mozilla Public
  4. // License, v. 2.0. If a copy of the MPL was not distributed with this file,
  5. // You can obtain one at https://mozilla.org/MPL/2.0/.
  6. package config
  7. import (
  8. "testing"
  9. "github.com/syncthing/syncthing/lib/util"
  10. )
  11. type TestStruct struct {
  12. Size Size `default:"10%"`
  13. }
  14. func TestSizeDefaults(t *testing.T) {
  15. x := &TestStruct{}
  16. util.SetDefaults(x)
  17. if !x.Size.Percentage() {
  18. t.Error("not percentage")
  19. }
  20. if x.Size.Value != 10 {
  21. t.Error("not ten")
  22. }
  23. }
  24. func TestParseSize(t *testing.T) {
  25. cases := []struct {
  26. in string
  27. ok bool
  28. val float64
  29. pct bool
  30. }{
  31. // We accept upper case SI units
  32. {"5K", true, 5e3, false}, // even when they should be lower case
  33. {"4 M", true, 4e6, false},
  34. {"3G", true, 3e9, false},
  35. {"2 T", true, 2e12, false},
  36. // We accept lower case SI units out of user friendliness
  37. {"1 k", true, 1e3, false},
  38. {"2m", true, 2e6, false},
  39. {"3 g", true, 3e9, false},
  40. {"4t", true, 4e12, false},
  41. // Fractions are OK
  42. {"123.456 k", true, 123.456e3, false},
  43. {"0.1234 m", true, 0.1234e6, false},
  44. {"3.45 g", true, 3.45e9, false},
  45. // We don't parse negative numbers
  46. {"-1", false, 0, false},
  47. {"-1k", false, 0, false},
  48. {"-0.45g", false, 0, false},
  49. // We accept various unit suffixes on the unit prefix
  50. {"100 KBytes", true, 100e3, false},
  51. {"100 Kbps", true, 100e3, false},
  52. {"100 MAU", true, 100e6, false},
  53. // Percentages are OK
  54. {"1%", true, 1, true},
  55. {"200%", true, 200, true}, // even large ones
  56. {"200K%", true, 200e3, true}, // even with prefixes, although this makes no sense
  57. {"2.34%", true, 2.34, true}, // fractions are A-ok
  58. // The empty string is a valid zero
  59. {"", true, 0, false},
  60. {" ", true, 0, false},
  61. }
  62. for _, tc := range cases {
  63. size, err := ParseSize(tc.in)
  64. if !tc.ok {
  65. if err == nil {
  66. t.Errorf("Unexpected nil error in UnmarshalText(%q)", tc.in)
  67. }
  68. continue
  69. }
  70. if err != nil {
  71. t.Errorf("Unexpected error in UnmarshalText(%q): %v", tc.in, err)
  72. continue
  73. }
  74. if size.BaseValue() > tc.val*1.001 || size.BaseValue() < tc.val*0.999 {
  75. // Allow 0.1% slop due to floating point multiplication
  76. t.Errorf("Incorrect value in UnmarshalText(%q): %v, wanted %v", tc.in, size.BaseValue(), tc.val)
  77. }
  78. if size.Percentage() != tc.pct {
  79. t.Errorf("Incorrect percentage bool in UnmarshalText(%q): %v, wanted %v", tc.in, size.Percentage(), tc.pct)
  80. }
  81. }
  82. }
  83. func TestFormatSI(t *testing.T) {
  84. cases := []struct {
  85. bytes int64
  86. result string
  87. }{
  88. {
  89. bytes: 0,
  90. result: "0 ", // space for unit
  91. },
  92. {
  93. bytes: 999,
  94. result: "999 ",
  95. },
  96. {
  97. bytes: 1000,
  98. result: "1.0 K",
  99. },
  100. {
  101. bytes: 1023 * 1000,
  102. result: "1.0 M",
  103. },
  104. {
  105. bytes: 5 * 1000 * 1000 * 1000,
  106. result: "5.0 G",
  107. },
  108. {
  109. bytes: 50000 * 1000 * 1000 * 1000 * 1000,
  110. result: "50000.0 T",
  111. },
  112. }
  113. for _, tc := range cases {
  114. res := formatSI(tc.bytes)
  115. if res != tc.result {
  116. t.Errorf("formatSI(%d) => %q, expected %q", tc.bytes, res, tc.result)
  117. }
  118. }
  119. }