test.go 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420
  1. package storage
  2. import (
  3. "fmt"
  4. "path"
  5. "testing"
  6. "github.com/opencost/opencost/core/pkg/util/json"
  7. )
  8. type testFileContent struct {
  9. Field1 int `json:"field_1"`
  10. Field2 string `json:"field_2"`
  11. }
  12. var tfc = testFileContent{
  13. Field1: 101,
  14. Field2: "TEST_FILE_CONTENT",
  15. }
  16. const testpath = "opencost/storage/"
  17. func createFiles(files []string, testName string, store Storage) error {
  18. b, err := json.Marshal(tfc)
  19. if err != nil {
  20. return fmt.Errorf("failed to marshal file content: %w", err)
  21. }
  22. for _, fileName := range files {
  23. filePath := path.Join(testpath, testName, fileName)
  24. err = store.Write(filePath, b)
  25. if err != nil {
  26. return fmt.Errorf("failed to write file '%s': %w ", filePath, err)
  27. }
  28. }
  29. return nil
  30. }
  31. func cleanupFiles(files []string, testName string, store Storage) error {
  32. for _, fileName := range files {
  33. filePath := path.Join(testpath, testName, fileName)
  34. err := store.Remove(filePath)
  35. if err != nil {
  36. return fmt.Errorf("failed to remove file '%s': %w ", filePath, err)
  37. }
  38. }
  39. return nil
  40. }
  41. func TestStorageList(t *testing.T, store Storage) {
  42. testName := "list"
  43. fileNames := []string{
  44. "/file0.json",
  45. "/file1.json",
  46. "/dir0/file2.json",
  47. "/dir0/file3.json",
  48. }
  49. err := createFiles(fileNames, testName, store)
  50. if err != nil {
  51. t.Errorf("failed to create files: %s", err)
  52. }
  53. defer func() {
  54. err = cleanupFiles(fileNames, testName, store)
  55. if err != nil {
  56. t.Errorf("failed to clean up files: %s", err)
  57. }
  58. }()
  59. testCases := map[string]struct {
  60. path string
  61. expected []string
  62. expectErr bool
  63. }{
  64. "base dir files": {
  65. path: path.Join(testpath, testName),
  66. expected: []string{
  67. "file0.json",
  68. "file1.json",
  69. },
  70. expectErr: false,
  71. },
  72. "single nested dir files": {
  73. path: path.Join(testpath, testName, "dir0"),
  74. expected: []string{
  75. "file2.json",
  76. "file3.json",
  77. },
  78. expectErr: false,
  79. },
  80. "nonexistent dir files": {
  81. path: path.Join(testpath, testName, "dir1"),
  82. expected: []string{},
  83. expectErr: false,
  84. },
  85. }
  86. for name, tc := range testCases {
  87. t.Run(name, func(t *testing.T) {
  88. fileList, err := store.List(tc.path)
  89. if tc.expectErr == (err == nil) {
  90. if tc.expectErr {
  91. t.Errorf("expected error was not thrown")
  92. return
  93. }
  94. t.Errorf("unexpected error: %s", err.Error())
  95. return
  96. }
  97. if len(fileList) != len(tc.expected) {
  98. t.Errorf("file list length does not match expected length, actual: %d, expected: %d", len(fileList), len(tc.expected))
  99. }
  100. expectedSet := map[string]struct{}{}
  101. for _, expName := range tc.expected {
  102. expectedSet[expName] = struct{}{}
  103. }
  104. for _, file := range fileList {
  105. _, ok := expectedSet[file.Name]
  106. if !ok {
  107. t.Errorf("unexpect file in list %s", file.Name)
  108. }
  109. if file.Size == 0 {
  110. t.Errorf("file size is not set")
  111. }
  112. if file.ModTime.IsZero() {
  113. t.Errorf("file mod time is not set")
  114. }
  115. }
  116. })
  117. }
  118. }
  119. func TestStorageListDirectories(t *testing.T, store Storage) {
  120. testName := "list_directories"
  121. fileNames := []string{
  122. "/file0.json",
  123. "/dir0/file2.json",
  124. "/dir0/file3.json",
  125. "/dir0/dir1/file4.json",
  126. "/dir0/dir2/file5.json",
  127. }
  128. err := createFiles(fileNames, testName, store)
  129. if err != nil {
  130. t.Errorf("failed to create files: %s", err)
  131. }
  132. defer func() {
  133. err = cleanupFiles(fileNames, testName, store)
  134. if err != nil {
  135. t.Errorf("failed to clean up files: %s", err)
  136. }
  137. }()
  138. testCases := map[string]struct {
  139. path string
  140. expected []string
  141. expectErr bool
  142. }{
  143. "base dir dir": {
  144. path: path.Join(testpath, testName),
  145. expected: []string{
  146. path.Join(testpath, testName, "dir0") + "/",
  147. },
  148. expectErr: false,
  149. },
  150. "single nested dir files": {
  151. path: path.Join(testpath, testName, "dir0"),
  152. expected: []string{
  153. path.Join(testpath, testName, "dir0", "dir1") + "/",
  154. path.Join(testpath, testName, "dir0", "dir2") + "/",
  155. },
  156. expectErr: false,
  157. },
  158. "dir with no sub dirs": {
  159. path: path.Join(testpath, testName, "dir0/dir1"),
  160. expected: []string{},
  161. expectErr: false,
  162. },
  163. "non-existent dir": {
  164. path: path.Join(testpath, testName, "dir1"),
  165. expected: []string{},
  166. expectErr: false,
  167. },
  168. }
  169. for name, tc := range testCases {
  170. t.Run(name, func(t *testing.T) {
  171. dirList, err := store.ListDirectories(tc.path)
  172. if tc.expectErr == (err == nil) {
  173. if tc.expectErr {
  174. t.Errorf("expected error was not thrown")
  175. return
  176. }
  177. t.Errorf("unexpected error: %s", err.Error())
  178. return
  179. }
  180. if len(dirList) != len(tc.expected) {
  181. t.Errorf("dir list length does not match expected length, actual: %d, expected: %d", len(dirList), len(tc.expected))
  182. }
  183. expectedSet := map[string]struct{}{}
  184. for _, expName := range tc.expected {
  185. expectedSet[expName] = struct{}{}
  186. }
  187. for _, dir := range dirList {
  188. _, ok := expectedSet[dir.Name]
  189. if !ok {
  190. t.Errorf("unexpect dir in list %s", dir.Name)
  191. }
  192. }
  193. })
  194. }
  195. }
  196. func TestStorageExists(t *testing.T, store Storage) {
  197. testName := "exists"
  198. fileNames := []string{
  199. "/file0.json",
  200. }
  201. err := createFiles(fileNames, testName, store)
  202. if err != nil {
  203. t.Errorf("failed to create files: %s", err)
  204. }
  205. defer func() {
  206. err = cleanupFiles(fileNames, testName, store)
  207. if err != nil {
  208. t.Errorf("failed to clean up files: %s", err)
  209. }
  210. }()
  211. testCases := map[string]struct {
  212. path string
  213. expected bool
  214. expectErr bool
  215. }{
  216. "file exists": {
  217. path: path.Join(testpath, testName, "file0.json"),
  218. expected: true,
  219. expectErr: false,
  220. },
  221. "file does not exist": {
  222. path: path.Join(testpath, testName, "file1.json"),
  223. expected: false,
  224. expectErr: false,
  225. },
  226. "dir does not exist": {
  227. path: path.Join(testpath, testName, "dir0/file.json"),
  228. expected: false,
  229. expectErr: false,
  230. },
  231. }
  232. for name, tc := range testCases {
  233. t.Run(name, func(t *testing.T) {
  234. exists, err := store.Exists(tc.path)
  235. if tc.expectErr == (err == nil) {
  236. if tc.expectErr {
  237. t.Errorf("expected error was not thrown")
  238. return
  239. }
  240. t.Errorf("unexpected error: %s", err.Error())
  241. return
  242. }
  243. if exists != tc.expected {
  244. t.Errorf("file exists output did not match expected")
  245. }
  246. })
  247. }
  248. }
  249. func TestStorageRead(t *testing.T, store Storage) {
  250. testName := "read"
  251. fileNames := []string{
  252. "/file0.json",
  253. }
  254. err := createFiles(fileNames, testName, store)
  255. if err != nil {
  256. t.Errorf("failed to create files: %s", err)
  257. }
  258. defer func() {
  259. err = cleanupFiles(fileNames, testName, store)
  260. if err != nil {
  261. t.Errorf("failed to clean up files: %s", err)
  262. }
  263. }()
  264. testCases := map[string]struct {
  265. path string
  266. expectErr bool
  267. }{
  268. "file exists": {
  269. path: path.Join(testpath, testName, "file0.json"),
  270. expectErr: false,
  271. },
  272. "file does not exist": {
  273. path: path.Join(testpath, testName, "file1.json"),
  274. expectErr: true,
  275. },
  276. "dir does not exist": {
  277. path: path.Join(testpath, testName, "dir0/file.json"),
  278. expectErr: true,
  279. },
  280. }
  281. for name, tc := range testCases {
  282. t.Run(name, func(t *testing.T) {
  283. b, err := store.Read(tc.path)
  284. if tc.expectErr && err != nil {
  285. return
  286. }
  287. if tc.expectErr == (err == nil) {
  288. if tc.expectErr {
  289. t.Errorf("expected error was not thrown")
  290. return
  291. }
  292. t.Errorf("unexpected error: %s", err.Error())
  293. return
  294. }
  295. var content testFileContent
  296. err = json.Unmarshal(b, &content)
  297. if err != nil {
  298. t.Errorf("could not unmarshal file content")
  299. return
  300. }
  301. if content != tfc {
  302. t.Errorf("file content did not match writen value")
  303. }
  304. })
  305. }
  306. }
  307. func TestStorageStat(t *testing.T, store Storage) {
  308. testName := "stat"
  309. fileNames := []string{
  310. "/file0.json",
  311. }
  312. err := createFiles(fileNames, testName, store)
  313. if err != nil {
  314. t.Errorf("failed to create files: %s", err)
  315. }
  316. defer func() {
  317. err = cleanupFiles(fileNames, testName, store)
  318. if err != nil {
  319. t.Errorf("failed to clean up files: %s", err)
  320. }
  321. }()
  322. testCases := map[string]struct {
  323. path string
  324. expected *StorageInfo
  325. expectErr bool
  326. }{
  327. "base dir": {
  328. path: path.Join(testpath, testName, "file0.json"),
  329. expected: &StorageInfo{
  330. Name: "file0.json",
  331. Size: 45,
  332. },
  333. expectErr: false,
  334. },
  335. "file does not exist": {
  336. path: path.Join(testpath, testName, "file1.json"),
  337. expected: nil,
  338. expectErr: true,
  339. },
  340. }
  341. for name, tc := range testCases {
  342. t.Run(name, func(t *testing.T) {
  343. status, err := store.Stat(tc.path)
  344. if tc.expectErr && err != nil {
  345. return
  346. }
  347. if tc.expectErr == (err == nil) {
  348. if tc.expectErr {
  349. t.Errorf("expected error was not thrown")
  350. return
  351. }
  352. t.Errorf("unexpected error: %s", err.Error())
  353. return
  354. }
  355. if status.Name != tc.expected.Name {
  356. t.Errorf("status name did name match expected, actual: %s, expected: %s", status.Name, tc.expected.Name)
  357. }
  358. if status.Size != tc.expected.Size {
  359. t.Errorf("status name did size match expected, actual: %d, expected: %d", status.Size, tc.expected.Size)
  360. }
  361. if status.ModTime.IsZero() {
  362. t.Errorf("status mod time is not set")
  363. }
  364. })
  365. }
  366. }