github.com/cozy/cozy-stack@v0.0.0-20240603063001-31110fa4cae1/tests/system/scalability/base_tests.rb (about) 1 require_relative '../boot' 2 3 def create_instances(names) 4 insts = Array.new(names.length) 5 names.each_with_index do |name, i| 6 insts[i] = Instance.create name: name 7 end 8 insts 9 end 10 11 def create_sharing(insts, obj) 12 inst_sharer = insts[0] 13 sharing = Sharing.new 14 sharing.rules << Rule.sync(obj) 15 sharing.members << inst_sharer 16 recipients = insts.drop 1 17 recipients.each do |inst| 18 contact = Contact.create inst_sharer, given_name: inst.name 19 sharing.members << contact 20 end 21 inst_sharer.register sharing 22 sleep 1 23 recipients.each do |inst| 24 inst.accept sharing 25 sleep 2 26 end 27 sharing 28 end 29 30 # Create a file with a fixed size, in KB 31 def create_file_with_size(inst, dir_id, size) 32 file_path = "tmp/#{Faker::Internet.unique.slug}.txt" 33 buffer = "a" * 1024 34 File.open(file_path, 'w') do |f| 35 size.to_i.times { f.write(buffer) } 36 end 37 opts = CozyFile.options_from_fixture file_path, dir_id: dir_id 38 CozyFile.create inst, opts 39 end 40 41 def create_files(inst, n_files, dir_id) 42 print "Create #{n_files} files... " 43 files = Array.new(n_files) 44 n_files.times do |i| 45 files[i] = create_file inst, dir_id, size 46 end 47 print "Done.\n" 48 files 49 end 50 51 def create_hierarchy(inst, root, n_elements, max_filesize = nil) 52 files = [] 53 dirs = [root] 54 n_elements.times do 55 create_dir_or_file inst, dirs, files, max_filesize 56 end 57 [dirs, files] 58 end 59 60 def get_hierarchy(inst, root) 61 dirs, files = Folder.children inst, root.path 62 63 if dirs.length > 0 64 dirs.each do |dir| 65 sdirs, sfiles = get_hierarchy inst, dir 66 dirs += sdirs 67 files += sfiles 68 end 69 end 70 dirs.unshift root 71 [dirs, files] 72 end 73 74 def create_file(inst, dir_id, filesize = nil) 75 if filesize.nil? 76 file_name = "#{Faker::Internet.unique.slug}.txt" 77 CozyFile.create inst, dir_id: dir_id, name: file_name 78 else 79 create_file_with_size inst, dir_id, filesize 80 end 81 end 82 83 def create_dir(inst, dir_id) 84 dir_name = Faker::Internet.unique.slug 85 parent = Folder.find inst, dir_id 86 path = "#{parent.path}/#{dir_name}" 87 Folder.create inst, dir_id: dir_id, name: dir_name, path: path 88 end 89 90 def create_dir_or_file(inst, dirs, files, max_filesize = nil) 91 dir_id = pick_random_element(dirs).couch_id 92 create_folder = [true, false].sample 93 94 if create_folder 95 dir = create_dir inst, dir_id 96 dirs << dir 97 else 98 filesize = Random.rand(1..max_filesize) unless max_filesize.nil? 99 file = create_file inst, dir_id, filesize 100 files << file 101 end 102 end 103 104 def remove_folder(inst, dirs, files) 105 return unless dirs.length > 2 106 107 removable_dirs = dirs - [dirs[0]] # do not remove the root folder 108 dir = pick_random_element removable_dirs 109 dir.remove inst 110 remove_folder_in_hierarchy dirs, files, dir 111 end 112 113 def remove_file(inst, files) 114 return unless files.length > 0 115 116 file = pick_random_element files 117 file.remove inst 118 files.delete file 119 end 120 121 def remove_folder_or_file(inst, dirs, files) 122 is_folder = [true, false].sample 123 if is_folder 124 remove_folder inst, dirs, files 125 else 126 remove_file inst, files 127 end 128 end 129 130 # Returns true if the element is part of the root's hierarchy 131 def child?(root, dirs, el) 132 return true unless el.dir_id != root.couch_id 133 134 parent = dirs.find { |dir| dir.couch_id == el.dir_id } 135 return false if parent.nil? 136 child? root, dirs, parent 137 end 138 139 # Remove all the descendants of the given folder 140 def remove_folder_in_hierarchy(dirs, files, folder) 141 dirs_to_del = dirs.map { |dir| dir if child? folder, dirs, dir }.compact 142 dirs_to_del << folder 143 files_to_del = files.map { |file| file if child? folder, dirs, file }.compact 144 145 dirs_to_del.each { |dir| dirs.delete dir } 146 files_to_del.each { |file| files.delete file } 147 end 148 149 def rename_dir_or_file(inst, dirs, files) 150 is_folder = [true, false].sample 151 if is_folder 152 dir = pick_random_element dirs 153 dir.rename inst, Faker::Internet.unique.slug unless dir.nil? 154 else 155 file = pick_random_element files 156 file.rename inst, "#{Faker::Internet.unique.slug}.txt" unless file.nil? 157 end 158 end 159 160 def rewrite_file(inst, files) 161 file = pick_random_element files 162 file.overwrite inst unless file.nil? 163 end 164 165 def move_dir_or_file(inst, dirs, files) 166 is_folder = [true, false].sample 167 parent = pick_random_element dirs 168 169 if is_folder 170 dir = pick_random_element dirs 171 dir.move_to inst, parent.couch_id unless dir.nil? 172 else 173 file = pick_random_element files 174 file.move_to inst, parent.couch_id unless file.nil? 175 end 176 end 177 178 def update_dir_or_file(inst, dirs, files) 179 case Random.rand(3) 180 when 0 181 rename_dir_or_file inst, dirs, files 182 when 1 183 move_dir_or_file inst, dirs, files 184 when 2 185 rewrite_file inst, files 186 end 187 end 188 189 # Randomly generate updates on instances 190 def generate_updates(insts, n_updates, *files) 191 return unless insts.length == files.length 192 193 n_updates.times do 194 i_inst = Random.rand insts.length 195 i_file = Random.rand files[i_inst].length 196 rename_or_rewrite insts[i_inst], files[i_inst][i_file] 197 end 198 end 199 200 def rename_or_rewrite(inst, file) 201 rename = [true, false].sample 202 if rename 203 file.rename inst, "#{Faker::Internet.unique.slug}.txt" 204 else 205 file.overwrite inst 206 end 207 end 208 209 # Run a diff on folders until they are even 210 def poll_for_diff(da, db) 211 printf "Waiting for shared files to be consistent in file system... " 212 start = Time.now 213 loop do 214 begin 215 diff = Helpers.fsdiff da, db 216 if diff.empty? 217 finish = Time.now 218 diff = finish - start 219 printf "Done in #{diff}s.\n" 220 break 221 end 222 rescue 223 end 224 sleep 2 225 end 226 end 227 228 def pick_random_element(array) 229 return nil if array.empty? 230 array.length == 1 ? array[0] : array[Random.rand array.length] 231 end