1# Copyright (c) Meta Platforms, Inc. and affiliates.
2#
3# This source code is licensed under the MIT license found in the
4# LICENSE file in the root directory of this source tree.
5
6class FileMock < File
7    @@exist_invocation_params = []
8    @@mocked_existing_files = []
9
10    @@delete_invocation_count = 0
11    @@deleted_files = []
12
13    @@open_files_with_mode = {}
14    @@open_invocation_count = 0
15
16    @@open_files = []
17
18    @@files_to_read = {}
19    attr_reader :collected_write
20    attr_reader :fsync_invocation_count
21
22    def initialize()
23        @collected_write = []
24        @fsync_invocation_count = 0
25    end
26
27    # Monkey patched exists? method.
28    # It is used also by the test runner, so it can't start monkey patched
29    # To use this, invoke the `is_testing` method before starting your test.
30    # Remember to invoke `reset` after the test.
31    def self.exist?(path)
32        @@exist_invocation_params.push(path)
33        return @@mocked_existing_files.include?(path)
34    end
35
36    def self.delete(path)
37        @@delete_invocation_count += 1
38        @@deleted_files.push(path)
39    end
40
41    def self.delete_invocation_count
42        return @@delete_invocation_count
43    end
44
45    def self.deleted_files
46        return @@deleted_files
47    end
48
49    # Getter for the `exist_invocation_params` to check that the exist method
50    # is invoked the right number of times with the right parameters
51    def self.exist_invocation_params()
52        return @@exist_invocation_params
53    end
54
55    # Set the list of files the test must return as existing
56    def self.mocked_existing_files(files)
57        @@mocked_existing_files = files
58    end
59
60    def self.open(path, mode, &block)
61        @@open_files_with_mode[path] = mode
62        @@open_invocation_count += 1
63        file = FileMock.new()
64        @@open_files.push(file)
65        yield(file)
66    end
67
68    def self.open_files_with_mode
69        return @@open_files_with_mode
70    end
71
72    def self.open_invocation_count
73        return @@open_invocation_count
74    end
75
76    def self.open_files
77        return @@open_files
78    end
79
80    def self.file_invocation_params
81        return @@file_invocation_params
82    end
83
84    def write(text)
85        @collected_write.push(text.to_s)
86    end
87
88    def fsync()
89        @fsync_invocation_count += 1
90    end
91
92
93    def self.files_to_read(files)
94        @@files_to_read = files
95    end
96
97    def self.read(filepath)
98        return @@files_to_read[filepath]
99    end
100
101    # Resets all the settings for the File mock
102    def self.reset()
103        @@delete_invocation_count = 0
104        @@deleted_files = []
105        @@open_files = []
106        @@open_files_with_mode = {}
107        @@open_invocation_count = 0
108        @@mocked_existing_files = []
109        @@file_invocation_params = []
110        @@exist_invocation_params = []
111        @@files_to_read = {}
112    end
113end
114