value_source_test.go 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246
  1. // Copyright 2025 The frp Authors
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. package v1
  15. import (
  16. "context"
  17. "os"
  18. "path/filepath"
  19. "testing"
  20. )
  21. func TestValueSource_Validate(t *testing.T) {
  22. tests := []struct {
  23. name string
  24. vs *ValueSource
  25. wantErr bool
  26. }{
  27. {
  28. name: "nil valueSource",
  29. vs: nil,
  30. wantErr: true,
  31. },
  32. {
  33. name: "unsupported type",
  34. vs: &ValueSource{
  35. Type: "unsupported",
  36. },
  37. wantErr: true,
  38. },
  39. {
  40. name: "file type without file config",
  41. vs: &ValueSource{
  42. Type: "file",
  43. File: nil,
  44. },
  45. wantErr: true,
  46. },
  47. {
  48. name: "valid file type with absolute path",
  49. vs: &ValueSource{
  50. Type: "file",
  51. File: &FileSource{
  52. Path: "/tmp/test",
  53. },
  54. },
  55. wantErr: false,
  56. },
  57. {
  58. name: "valid file type with relative path",
  59. vs: &ValueSource{
  60. Type: "file",
  61. File: &FileSource{
  62. Path: "configs/token",
  63. },
  64. },
  65. wantErr: false,
  66. },
  67. }
  68. for _, tt := range tests {
  69. t.Run(tt.name, func(t *testing.T) {
  70. err := tt.vs.Validate()
  71. if (err != nil) != tt.wantErr {
  72. t.Errorf("ValueSource.Validate() error = %v, wantErr %v", err, tt.wantErr)
  73. }
  74. })
  75. }
  76. }
  77. func TestFileSource_Validate(t *testing.T) {
  78. tests := []struct {
  79. name string
  80. fs *FileSource
  81. wantErr bool
  82. }{
  83. {
  84. name: "nil fileSource",
  85. fs: nil,
  86. wantErr: true,
  87. },
  88. {
  89. name: "empty path",
  90. fs: &FileSource{
  91. Path: "",
  92. },
  93. wantErr: true,
  94. },
  95. {
  96. name: "relative path (allowed)",
  97. fs: &FileSource{
  98. Path: "relative/path",
  99. },
  100. wantErr: false,
  101. },
  102. {
  103. name: "absolute path",
  104. fs: &FileSource{
  105. Path: "/absolute/path",
  106. },
  107. wantErr: false,
  108. },
  109. }
  110. for _, tt := range tests {
  111. t.Run(tt.name, func(t *testing.T) {
  112. err := tt.fs.Validate()
  113. if (err != nil) != tt.wantErr {
  114. t.Errorf("FileSource.Validate() error = %v, wantErr %v", err, tt.wantErr)
  115. }
  116. })
  117. }
  118. }
  119. func TestFileSource_Resolve(t *testing.T) {
  120. // Create a temporary file for testing
  121. tmpDir := t.TempDir()
  122. testFile := filepath.Join(tmpDir, "test_token")
  123. testContent := "test-token-value\n\t "
  124. expectedContent := "test-token-value"
  125. err := os.WriteFile(testFile, []byte(testContent), 0o600)
  126. if err != nil {
  127. t.Fatalf("failed to create test file: %v", err)
  128. }
  129. tests := []struct {
  130. name string
  131. fs *FileSource
  132. want string
  133. wantErr bool
  134. }{
  135. {
  136. name: "valid file path",
  137. fs: &FileSource{
  138. Path: testFile,
  139. },
  140. want: expectedContent,
  141. wantErr: false,
  142. },
  143. {
  144. name: "non-existent file",
  145. fs: &FileSource{
  146. Path: "/non/existent/file",
  147. },
  148. want: "",
  149. wantErr: true,
  150. },
  151. {
  152. name: "path traversal attempt (should fail validation)",
  153. fs: &FileSource{
  154. Path: "../../../etc/passwd",
  155. },
  156. want: "",
  157. wantErr: true,
  158. },
  159. }
  160. for _, tt := range tests {
  161. t.Run(tt.name, func(t *testing.T) {
  162. got, err := tt.fs.Resolve(context.Background())
  163. if (err != nil) != tt.wantErr {
  164. t.Errorf("FileSource.Resolve() error = %v, wantErr %v", err, tt.wantErr)
  165. return
  166. }
  167. if got != tt.want {
  168. t.Errorf("FileSource.Resolve() = %v, want %v", got, tt.want)
  169. }
  170. })
  171. }
  172. }
  173. func TestValueSource_Resolve(t *testing.T) {
  174. // Create a temporary file for testing
  175. tmpDir := t.TempDir()
  176. testFile := filepath.Join(tmpDir, "test_token")
  177. testContent := "test-token-value"
  178. err := os.WriteFile(testFile, []byte(testContent), 0o600)
  179. if err != nil {
  180. t.Fatalf("failed to create test file: %v", err)
  181. }
  182. tests := []struct {
  183. name string
  184. vs *ValueSource
  185. want string
  186. wantErr bool
  187. }{
  188. {
  189. name: "valid file type",
  190. vs: &ValueSource{
  191. Type: "file",
  192. File: &FileSource{
  193. Path: testFile,
  194. },
  195. },
  196. want: testContent,
  197. wantErr: false,
  198. },
  199. {
  200. name: "unsupported type",
  201. vs: &ValueSource{
  202. Type: "unsupported",
  203. },
  204. want: "",
  205. wantErr: true,
  206. },
  207. {
  208. name: "file type with path traversal",
  209. vs: &ValueSource{
  210. Type: "file",
  211. File: &FileSource{
  212. Path: "../../../etc/passwd",
  213. },
  214. },
  215. want: "",
  216. wantErr: true,
  217. },
  218. }
  219. ctx := context.Background()
  220. for _, tt := range tests {
  221. t.Run(tt.name, func(t *testing.T) {
  222. got, err := tt.vs.Resolve(ctx)
  223. if (err != nil) != tt.wantErr {
  224. t.Errorf("ValueSource.Resolve() error = %v, wantErr %v", err, tt.wantErr)
  225. return
  226. }
  227. if got != tt.want {
  228. t.Errorf("ValueSource.Resolve() = %v, want %v", got, tt.want)
  229. }
  230. })
  231. }
  232. }