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