file_spec.rb 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  1. # Copyright (C) 2012-2022 Zammad Foundation, https://zammad-foundation.org/
  2. require 'rails_helper'
  3. RSpec.describe Store::Provider::File do
  4. before { FileUtils.rm_rf(Rails.root.join('storage/fs', sha[0, 4])) }
  5. after { FileUtils.rm_rf(Rails.root.join('storage/fs', sha[0, 4])) }
  6. let(:data) { 'foo' }
  7. let(:sha) { Store::File.checksum(data) }
  8. let(:filepath) { Rails.root.join('storage/fs/2c26/b46b/68ffc/68ff9/9b453c1/d304134/13422d706483bfa0f98a5e886266e7ae') }
  9. describe '.get_location' do
  10. context 'with a valid SHA256 digest' do
  11. let(:sha) { '0000111122222333334444444555555566666666666666666666666666666666' }
  12. it 'returns a Pathname matching the SHA digest (split into chunks of 4, 4, 5, 5, 7, 7, & 32 chars)' do
  13. expect(described_class.get_location(sha))
  14. .to eq(Rails.root.join('storage/fs/0000/1111/22222/33333/4444444/5555555/66666666666666666666666666666666'))
  15. end
  16. end
  17. end
  18. describe '.add' do
  19. context 'when no matching file exists' do
  20. it 'writes the file to disk' do
  21. expect { described_class.add(data, sha) }
  22. .to change { File.exist?(filepath) }.to(true)
  23. expect(File.read(filepath)).to eq(data)
  24. end
  25. it 'sets permissions on the new file to 600' do
  26. described_class.add(data, sha)
  27. expect(File.stat(filepath).mode & 0o777).to eq(0o600)
  28. end
  29. end
  30. context 'when a matching file exists' do
  31. before { FileUtils.mkdir_p(filepath.parent) }
  32. context 'and its contents match the SHA digest of its filepath' do
  33. before do
  34. File.write(filepath, 'foo')
  35. File.chmod(0o755, filepath)
  36. end
  37. it 'sets file permissions to 600' do
  38. expect { described_class.add(data, sha) }
  39. .to change { File.stat(filepath).mode & 0o777 }.to(0o600)
  40. end
  41. end
  42. context 'and its contents do NOT match the SHA digest of its filepath' do
  43. before { File.write(filepath, 'bar') }
  44. it 'replaces the corrupt file with the specified contents' do
  45. expect { described_class.add(data, sha) }
  46. .to change { File.read(filepath) }.to('foo')
  47. end
  48. end
  49. end
  50. end
  51. describe '.get' do
  52. context 'when a file exists for the given SHA digest' do
  53. before { FileUtils.mkdir_p(filepath.parent) }
  54. context 'and its contents match the digest' do
  55. before { File.write(filepath, data) }
  56. it 'returns the contents of the file' do
  57. expect(described_class.get(sha)).to eq('foo')
  58. end
  59. end
  60. context 'and its contents do NOT match the digest' do
  61. before { File.write(filepath, 'bar') }
  62. it 'raises an error' do
  63. expect { described_class.get(sha) }
  64. .to raise_error(StandardError)
  65. end
  66. end
  67. end
  68. context 'when NO file exists for the given SHA digest' do
  69. it 'raises an error' do
  70. expect { described_class.get(sha) }
  71. .to raise_error(Errno::ENOENT)
  72. end
  73. end
  74. end
  75. describe '.delete' do
  76. before do
  77. FileUtils.mkdir_p(filepath.parent)
  78. File.write(filepath, data)
  79. end
  80. it 'deletes the file' do
  81. expect { described_class.delete(sha) }
  82. .to change { File.exist?(filepath) }.to(false)
  83. end
  84. context 'when the file’s parent directories contain other files' do
  85. before { FileUtils.touch(filepath.parent.join('baz')) }
  86. it 'leaves non-empty subdirectories in place' do
  87. expect { described_class.delete(sha) }
  88. .not_to change { Dir.exist?(filepath.parent) }
  89. end
  90. end
  91. context 'when the file’s parent directories contain no other files' do
  92. it 'deletes empty parent subdirectories, up to /storage/fs' do
  93. expect { described_class.delete(sha) }
  94. .to change { Dir.empty?(Rails.root.join('storage/fs')) }.to(true)
  95. end
  96. end
  97. end
  98. end