active_encode 1.2.0 → 1.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (141) hide show
  1. checksums.yaml +4 -4
  2. data/.circleci/config.yml +1 -0
  3. data/active_encode.gemspec +1 -2
  4. data/lib/active_encode/engine_adapters/pass_through_adapter.rb +28 -7
  5. data/lib/active_encode/version.rb +1 -1
  6. metadata +4 -274
  7. data/spec/controllers/encode_record_controller_spec.rb +0 -53
  8. data/spec/fixtures//"file_with_double_quote/".low.mp4 +0 -0
  9. data/spec/fixtures//"file_with_double_quote/".mp4 +0 -0
  10. data/spec/fixtures/'file_with_single_quote'.low.mp4 +0 -0
  11. data/spec/fixtures/'file_with_single_quote'.mp4 +0 -0
  12. data/spec/fixtures/@/341/213/210/341/213/263/341/214/205/341/210/205 /341/210/233/341/210/255 /341/211/242. /341/210/206/341/212/225 /341/214/250/341/210/255/341/210/265. /341/210/205 /341/212/240/341/211/265/341/210/213/341/210/260!@#$^^&$%&.low.mov +0 -0
  13. data/spec/fixtures/@/341/213/210/341/213/263/341/214/205/341/210/205 /341/210/233/341/210/255 /341/211/242. /341/210/206/341/212/225 /341/214/250/341/210/255/341/210/265. /341/210/205 /341/212/240/341/211/265/341/210/213/341/210/260!@#$^^&$%&.mov +0 -0
  14. data/spec/fixtures/Bars_512kb.mp4 +0 -0
  15. data/spec/fixtures/elastic_transcoder/input_completed.json +0 -1
  16. data/spec/fixtures/elastic_transcoder/input_generic.json +0 -1
  17. data/spec/fixtures/elastic_transcoder/input_progressing.json +0 -1
  18. data/spec/fixtures/elastic_transcoder/job_canceled.json +0 -1
  19. data/spec/fixtures/elastic_transcoder/job_completed.json +0 -1
  20. data/spec/fixtures/elastic_transcoder/job_created.json +0 -1
  21. data/spec/fixtures/elastic_transcoder/job_failed.json +0 -1
  22. data/spec/fixtures/elastic_transcoder/job_progressing.json +0 -1
  23. data/spec/fixtures/elastic_transcoder/output_canceled.json +0 -1
  24. data/spec/fixtures/elastic_transcoder/output_completed.json +0 -1
  25. data/spec/fixtures/elastic_transcoder/output_failed.json +0 -1
  26. data/spec/fixtures/elastic_transcoder/output_progressing.json +0 -1
  27. data/spec/fixtures/elastic_transcoder/output_submitted.json +0 -1
  28. data/spec/fixtures/ffmpeg/cancelled-id/cancelled +0 -0
  29. data/spec/fixtures/ffmpeg/cancelled-id/error.log +0 -0
  30. data/spec/fixtures/ffmpeg/cancelled-id/exit_status.code +0 -1
  31. data/spec/fixtures/ffmpeg/cancelled-id/input_metadata +0 -90
  32. data/spec/fixtures/ffmpeg/cancelled-id/pid +0 -1
  33. data/spec/fixtures/ffmpeg/cancelled-id/progress +0 -11
  34. data/spec/fixtures/ffmpeg/completed-id/error.log +0 -0
  35. data/spec/fixtures/ffmpeg/completed-id/exit_status.code +0 -1
  36. data/spec/fixtures/ffmpeg/completed-id/input_metadata +0 -102
  37. data/spec/fixtures/ffmpeg/completed-id/output_metadata-high +0 -90
  38. data/spec/fixtures/ffmpeg/completed-id/output_metadata-low +0 -90
  39. data/spec/fixtures/ffmpeg/completed-id/pid +0 -1
  40. data/spec/fixtures/ffmpeg/completed-id/progress +0 -11
  41. data/spec/fixtures/ffmpeg/completed-id/video-high.mp4 +0 -0
  42. data/spec/fixtures/ffmpeg/completed-id/video-low.mp4 +0 -0
  43. data/spec/fixtures/ffmpeg/completed-with-warnings-id/error.log +0 -3
  44. data/spec/fixtures/ffmpeg/completed-with-warnings-id/exit_status.code +0 -1
  45. data/spec/fixtures/ffmpeg/completed-with-warnings-id/input_metadata +0 -102
  46. data/spec/fixtures/ffmpeg/completed-with-warnings-id/output_metadata-high +0 -90
  47. data/spec/fixtures/ffmpeg/completed-with-warnings-id/output_metadata-low +0 -90
  48. data/spec/fixtures/ffmpeg/completed-with-warnings-id/pid +0 -1
  49. data/spec/fixtures/ffmpeg/completed-with-warnings-id/progress +0 -11
  50. data/spec/fixtures/ffmpeg/completed-with-warnings-id/video-high.mp4 +0 -0
  51. data/spec/fixtures/ffmpeg/completed-with-warnings-id/video-low.mp4 +0 -0
  52. data/spec/fixtures/ffmpeg/failed-id/error.log +0 -1
  53. data/spec/fixtures/ffmpeg/failed-id/exit_status.code +0 -1
  54. data/spec/fixtures/ffmpeg/failed-id/input_metadata +0 -90
  55. data/spec/fixtures/ffmpeg/failed-id/pid +0 -1
  56. data/spec/fixtures/ffmpeg/failed-id/progress +0 -11
  57. data/spec/fixtures/ffmpeg/incomplete-id/error.log +0 -0
  58. data/spec/fixtures/ffmpeg/incomplete-id/exit_status.code +0 -1
  59. data/spec/fixtures/ffmpeg/incomplete-id/input_metadata +0 -102
  60. data/spec/fixtures/ffmpeg/incomplete-id/output_metadata-high +0 -90
  61. data/spec/fixtures/ffmpeg/incomplete-id/output_metadata-low +0 -90
  62. data/spec/fixtures/ffmpeg/incomplete-id/pid +0 -1
  63. data/spec/fixtures/ffmpeg/incomplete-id/progress +0 -11
  64. data/spec/fixtures/ffmpeg/incomplete-id/video-high.mp4 +0 -0
  65. data/spec/fixtures/ffmpeg/incomplete-id/video-low.mp4 +0 -0
  66. data/spec/fixtures/ffmpeg/running-id/error.log +0 -0
  67. data/spec/fixtures/ffmpeg/running-id/input_metadata +0 -90
  68. data/spec/fixtures/ffmpeg/running-id/pid +0 -1
  69. data/spec/fixtures/ffmpeg/running-id/progress +0 -11
  70. data/spec/fixtures/file with space.low.mp4 +0 -0
  71. data/spec/fixtures/file with space.mp4 +0 -0
  72. data/spec/fixtures/file.with :=+%sp3c!l-ch4cts().mp4 +0 -0
  73. data/spec/fixtures/file.with...periods.mp4 +0 -0
  74. data/spec/fixtures/file_without_metadata.low.webm +0 -0
  75. data/spec/fixtures/file_without_metadata.mp4 +0 -0
  76. data/spec/fixtures/file_without_metadata.webm +0 -0
  77. data/spec/fixtures/fireworks.low.mp4 +0 -0
  78. data/spec/fixtures/fireworks.mp4 +0 -0
  79. data/spec/fixtures/matterhorn/cancelled_response.xml +0 -323
  80. data/spec/fixtures/matterhorn/completed_response.xml +0 -4
  81. data/spec/fixtures/matterhorn/create_response.xml +0 -300
  82. data/spec/fixtures/matterhorn/delete_track_response.xml +0 -2
  83. data/spec/fixtures/matterhorn/failed_response.xml +0 -4
  84. data/spec/fixtures/matterhorn/purged_response.xml +0 -342
  85. data/spec/fixtures/matterhorn/running_response.xml +0 -1
  86. data/spec/fixtures/matterhorn/stop_completed_response.xml +0 -228
  87. data/spec/fixtures/matterhorn/stop_running_response.xml +0 -339
  88. data/spec/fixtures/media_convert/endpoints.json +0 -1
  89. data/spec/fixtures/media_convert/job_canceled.json +0 -412
  90. data/spec/fixtures/media_convert/job_canceling.json +0 -1
  91. data/spec/fixtures/media_convert/job_completed.json +0 -359
  92. data/spec/fixtures/media_convert/job_completed_detail.json +0 -1
  93. data/spec/fixtures/media_convert/job_completed_detail_query.json +0 -1
  94. data/spec/fixtures/media_convert/job_completed_empty_detail.json +0 -1
  95. data/spec/fixtures/media_convert/job_created.json +0 -408
  96. data/spec/fixtures/media_convert/job_failed.json +0 -406
  97. data/spec/fixtures/media_convert/job_progressing.json +0 -414
  98. data/spec/fixtures/pass_through/cancelled-id/cancelled +0 -0
  99. data/spec/fixtures/pass_through/cancelled-id/input_metadata +0 -90
  100. data/spec/fixtures/pass_through/completed-id/completed +0 -0
  101. data/spec/fixtures/pass_through/completed-id/input_metadata +0 -102
  102. data/spec/fixtures/pass_through/completed-id/output_metadata-high +0 -90
  103. data/spec/fixtures/pass_through/completed-id/output_metadata-low +0 -90
  104. data/spec/fixtures/pass_through/completed-id/video-high.mp4 +0 -0
  105. data/spec/fixtures/pass_through/completed-id/video-low.mp4 +0 -0
  106. data/spec/fixtures/pass_through/failed-id/error.log +0 -1
  107. data/spec/fixtures/pass_through/failed-id/input_metadata +0 -90
  108. data/spec/fixtures/pass_through/running-id/input_metadata +0 -90
  109. data/spec/fixtures/zencoder/job_create.json +0 -1
  110. data/spec/fixtures/zencoder/job_details_cancelled.json +0 -1
  111. data/spec/fixtures/zencoder/job_details_completed.json +0 -1
  112. data/spec/fixtures/zencoder/job_details_create.json +0 -1
  113. data/spec/fixtures/zencoder/job_details_failed.json +0 -73
  114. data/spec/fixtures/zencoder/job_details_running.json +0 -1
  115. data/spec/fixtures/zencoder/job_progress_cancelled.json +0 -13
  116. data/spec/fixtures/zencoder/job_progress_completed.json +0 -13
  117. data/spec/fixtures/zencoder/job_progress_create.json +0 -1
  118. data/spec/fixtures/zencoder/job_progress_failed.json +0 -13
  119. data/spec/fixtures/zencoder/job_progress_running.json +0 -1
  120. data/spec/integration/elastic_transcoder_adapter_spec.rb +0 -218
  121. data/spec/integration/ffmpeg_adapter_spec.rb +0 -535
  122. data/spec/integration/matterhorn_adapter_spec.rb +0 -130
  123. data/spec/integration/media_convert_adapter_spec.rb +0 -321
  124. data/spec/integration/pass_through_adapter_spec.rb +0 -293
  125. data/spec/integration/zencoder_adapter_spec.rb +0 -391
  126. data/spec/rails_helper.rb +0 -25
  127. data/spec/routing/encode_record_controller_routing_spec.rb +0 -10
  128. data/spec/spec_helper.rb +0 -20
  129. data/spec/test_app_templates/lib/generators/test_app_generator.rb +0 -16
  130. data/spec/units/callbacks_spec.rb +0 -66
  131. data/spec/units/core_spec.rb +0 -160
  132. data/spec/units/engine_adapter_spec.rb +0 -67
  133. data/spec/units/file_locator_spec.rb +0 -129
  134. data/spec/units/filename_sanitizer_spec.rb +0 -20
  135. data/spec/units/global_id_spec.rb +0 -50
  136. data/spec/units/input_spec.rb +0 -40
  137. data/spec/units/output_spec.rb +0 -42
  138. data/spec/units/persistence_spec.rb +0 -61
  139. data/spec/units/polling_job_spec.rb +0 -87
  140. data/spec/units/polling_spec.rb +0 -23
  141. data/spec/units/status_spec.rb +0 -81
@@ -1,535 +0,0 @@
1
- # frozen_string_literal: true
2
- require 'rails_helper'
3
- require 'active_encode/spec/shared_specs'
4
-
5
- describe ActiveEncode::EngineAdapters::FfmpegAdapter do
6
- around do |example|
7
- ActiveEncode::Base.engine_adapter = :ffmpeg
8
-
9
- Dir.mktmpdir do |dir|
10
- @dir = dir
11
- example.run
12
- Dir.foreach(dir) do |e|
13
- next if e == "." || e == ".."
14
- FileUtils.rm_rf(File.join(dir, e))
15
- end
16
- end
17
-
18
- ActiveEncode::Base.engine_adapter = :test
19
- end
20
-
21
- let!(:work_dir) { stub_const "ActiveEncode::EngineAdapters::FfmpegAdapter::WORK_DIR", @dir }
22
- let(:file) { "file://" + Rails.root.join('..', 'spec', 'fixtures', 'fireworks.mp4').to_s }
23
- let(:created_job) do
24
- ActiveEncode::Base.create(file, outputs: [{ label: "low", ffmpeg_opt: "-s 640x480", extension: "mp4" }, { label: "high", ffmpeg_opt: "-s 1280x720", extension: "mp4" }])
25
- end
26
- let(:running_job) do
27
- allow(Process).to receive(:getpgid).and_return 8888
28
- find_encode "running-id"
29
- end
30
- let(:canceled_job) do
31
- find_encode 'cancelled-id'
32
- end
33
- let(:cancelling_job) do
34
- allow(Process).to receive(:kill).and_return(nil)
35
- encode = find_encode 'running-id'
36
- File.write "#{work_dir}/running-id/cancelled", ""
37
- encode
38
- end
39
- let(:completed_job) { find_encode "completed-id" }
40
- let(:completed_with_warnings_job) { find_encode "completed-with-warnings-id" }
41
- let(:incomplete_job) { find_encode "incomplete-id" }
42
- let(:failed_job) { find_encode 'failed-id' }
43
- let(:completed_tech_metadata) do
44
- {
45
- audio_bitrate: 171_030,
46
- audio_codec: 'mp4a-40-2',
47
- duration: 6315,
48
- file_size: 199_160,
49
- frame_rate: 23.719,
50
- height: 110.0,
51
- id: "99999",
52
- url: "/home/pdinh/Downloads/videoshort.mp4",
53
- video_bitrate: 74_477,
54
- video_codec: 'avc1',
55
- width: 200.0
56
- }
57
- end
58
- let(:completed_output) { [{ id: "99999" }] }
59
- let(:failed_tech_metadata) { {} }
60
-
61
- it_behaves_like "an ActiveEncode::EngineAdapter"
62
-
63
- def find_encode(id)
64
- # Precreate ffmpeg output directory and files
65
- FileUtils.copy_entry "spec/fixtures/ffmpeg/#{id}", "#{work_dir}/#{id}"
66
-
67
- # Simulate that progress is modified later than other files
68
- sleep 0.1
69
- FileUtils.touch "#{work_dir}/#{id}/progress"
70
- FileUtils.touch Dir.glob("#{work_dir}/#{id}/*.mp4")
71
-
72
- # Stub out system calls
73
- allow_any_instance_of(ActiveEncode::EngineAdapters::FfmpegAdapter).to receive(:`).and_return(1234)
74
-
75
- ActiveEncode::Base.find(id)
76
- end
77
-
78
- describe "#create" do
79
- subject { created_job }
80
-
81
- it "creates a directory whose name is the encode id" do
82
- expect(File).to exist("#{work_dir}/#{subject.id}")
83
- end
84
-
85
- context "input file exists" do
86
- it "has the input technical metadata in a file" do
87
- expect(File.read("#{work_dir}/#{subject.id}/input_metadata")).not_to be_empty
88
- end
89
-
90
- it "has the pid in a file" do
91
- expect(File.read("#{work_dir}/#{subject.id}/pid")).not_to be_empty
92
- end
93
- end
94
-
95
- context "input file doesn't exist" do
96
- let(:missing_file) { "file:///a_bogus_file.mp4" }
97
- let(:missing_job) { ActiveEncode::Base.create(missing_file, outputs: [{ label: "low", ffmpeg_opt: "-s 640x480", extension: 'mp4' }]) }
98
-
99
- it "returns the encode with correct error" do
100
- expect(missing_job.errors).to include("#{missing_file} does not exist or is not accessible")
101
- expect(missing_job.percent_complete).to be 1
102
- end
103
- end
104
-
105
- context "input file is not media" do
106
- let(:nonmedia_file) { "file://" + Rails.root.join('Gemfile').to_s }
107
- let(:nonmedia_job) { ActiveEncode::Base.create(nonmedia_file, outputs: [{ label: "low", ffmpeg_opt: "-s 640x480", extension: 'mp4' }]) }
108
-
109
- it "returns the encode with correct error" do
110
- expect(nonmedia_job.errors).to include("Error inspecting input: #{nonmedia_file}")
111
- expect(nonmedia_job.percent_complete).to be 1
112
- end
113
- end
114
-
115
- context "input file format does not match extension" do
116
- let(:improper_format_file) { "file://" + Rails.root.join('..', 'spec', 'fixtures', 'file_without_metadata.mp4').to_s }
117
- let(:improper_format_job) { ActiveEncode::Base.create(improper_format_file, outputs: [{ label: "low", ffmpeg_opt: "-s 640x480", extension: 'mp4' }]) }
118
-
119
- it "returns the encode with correct error" do
120
- expect(improper_format_job.errors).to include("Error inspecting input: #{improper_format_file}")
121
- expect(improper_format_job.percent_complete).to be 1
122
- end
123
- end
124
-
125
- context "input file with missing metadata" do
126
- let(:file_without_metadata) { "file://" + Rails.root.join('..', 'spec', 'fixtures', 'file_without_metadata.webm').to_s }
127
- let!(:create_without_metadata_job) { ActiveEncode::Base.create(file_without_metadata, outputs: [{ label: "low", ffmpeg_opt: "-s 640x480", extension: 'mp4' }]) }
128
- let(:find_without_metadata_job) { ActiveEncode::Base.find create_without_metadata_job.id }
129
-
130
- it "does not have errors" do
131
- sleep 2
132
- expect(find_without_metadata_job.errors).to be_empty
133
- end
134
-
135
- it "has the input technical metadata in a file" do
136
- expect(File.read("#{work_dir}/#{create_without_metadata_job.id}/input_metadata")).not_to be_empty
137
- end
138
-
139
- it "has the pid in a file" do
140
- expect(File.read("#{work_dir}/#{create_without_metadata_job.id}/pid")).not_to be_empty
141
- end
142
-
143
- it "assigns the correct duration to the encode" do
144
- expect(create_without_metadata_job.input.duration).to eq 68_653
145
- expect(find_without_metadata_job.input.duration).to eq 68_653
146
- end
147
-
148
- context 'when uri encoded' do
149
- let(:file_without_metadata) { Addressable::URI.encode("file://" + Rails.root.join('..', 'spec', 'fixtures', 'file_without_metadata.webm').to_s) }
150
-
151
- it "does not have errors" do
152
- sleep 2
153
- expect(find_without_metadata_job.errors).to be_empty
154
- end
155
-
156
- it "has the input technical metadata in a file" do
157
- expect(File.read("#{work_dir}/#{create_without_metadata_job.id}/input_metadata")).not_to be_empty
158
- end
159
-
160
- it "has the pid in a file" do
161
- expect(File.read("#{work_dir}/#{create_without_metadata_job.id}/pid")).not_to be_empty
162
- end
163
-
164
- it "assigns the correct duration to the encode" do
165
- expect(create_without_metadata_job.input.duration).to eq 68_653
166
- expect(find_without_metadata_job.input.duration).to eq 68_653
167
- end
168
- end
169
- end
170
-
171
- context "input filename with spaces" do
172
- let(:file_with_space) { "file://" + Rails.root.join('..', 'spec', 'fixtures', 'file with space.mp4').to_s }
173
- let!(:create_space_job) { ActiveEncode::Base.create(file_with_space, outputs: [{ label: "low", ffmpeg_opt: "-s 640x480", extension: 'mp4' }]) }
174
- let(:find_space_job) { ActiveEncode::Base.find create_space_job.id }
175
-
176
- it "does not have errors" do
177
- sleep 2
178
- expect(find_space_job.errors).to be_empty
179
- end
180
-
181
- it "has the input technical metadata in a file" do
182
- expect(File.read("#{work_dir}/#{create_space_job.id}/input_metadata")).not_to be_empty
183
- end
184
-
185
- it "has the pid in a file" do
186
- expect(File.read("#{work_dir}/#{create_space_job.id}/pid")).not_to be_empty
187
- end
188
-
189
- context 'when uri encoded' do
190
- let(:file_with_space) { Addressable::URI.encode("file://" + Rails.root.join('..', 'spec', 'fixtures', 'file with space.mp4').to_s) }
191
-
192
- it "does not have errors" do
193
- sleep 2
194
- expect(find_space_job.errors).to be_empty
195
- end
196
-
197
- it "has the input technical metadata in a file" do
198
- expect(File.read("#{work_dir}/#{create_space_job.id}/input_metadata")).not_to be_empty
199
- end
200
-
201
- it "has the pid in a file" do
202
- expect(File.read("#{work_dir}/#{create_space_job.id}/pid")).not_to be_empty
203
- end
204
- end
205
- end
206
-
207
- context "input filename with single quotes" do
208
- let(:file_with_single_quote) { "file://" + Rails.root.join('..', 'spec', 'fixtures', "'file_with_single_quote'.mp4").to_s }
209
- let!(:create_single_quote_job) { ActiveEncode::Base.create(file_with_single_quote, outputs: [{ label: "low", ffmpeg_opt: "-s 640x480", extension: 'mp4' }]) }
210
- let(:find_single_quote_job) { ActiveEncode::Base.find create_single_quote_job.id }
211
-
212
- it "does not have errors" do
213
- sleep 2
214
- expect(find_single_quote_job.errors).to be_empty
215
- end
216
-
217
- it "has the input technical metadata in a file" do
218
- expect(File.read("#{work_dir}/#{create_single_quote_job.id}/input_metadata")).not_to be_empty
219
- end
220
-
221
- it "has the pid in a file" do
222
- expect(File.read("#{work_dir}/#{create_single_quote_job.id}/pid")).not_to be_empty
223
- end
224
-
225
- context 'when uri encoded' do
226
- let(:file_with_single_quote) { Addressable::URI.encode("file://" + Rails.root.join('..', 'spec', 'fixtures', "'file_with_single_quote'.mp4").to_s) }
227
-
228
- it "does not have errors" do
229
- sleep 2
230
- expect(find_single_quote_job.errors).to be_empty
231
- end
232
-
233
- it "has the input technical metadata in a file" do
234
- expect(File.read("#{work_dir}/#{create_single_quote_job.id}/input_metadata")).not_to be_empty
235
- end
236
-
237
- it "has the pid in a file" do
238
- expect(File.read("#{work_dir}/#{create_single_quote_job.id}/pid")).not_to be_empty
239
- end
240
- end
241
- end
242
-
243
- context "input filename with double quotes" do
244
- let(:file_with_double_quote) { "file://" + Rails.root.join('..', 'spec', 'fixtures', '"file_with_double_quote".mp4').to_s }
245
- let!(:create_double_quote_job) { ActiveEncode::Base.create(file_with_double_quote, outputs: [{ label: "low", ffmpeg_opt: "-s 640x480", extension: 'mp4' }]) }
246
- let(:find_double_quote_job) { ActiveEncode::Base.find create_double_quote_job.id }
247
-
248
- it "does not have errors" do
249
- sleep 2
250
- expect(find_double_quote_job.errors).to be_empty
251
- end
252
-
253
- it "has the input technical metadata in a file" do
254
- expect(File.read("#{work_dir}/#{create_double_quote_job.id}/input_metadata")).not_to be_empty
255
- end
256
-
257
- it "has the pid in a file" do
258
- expect(File.read("#{work_dir}/#{create_double_quote_job.id}/pid")).not_to be_empty
259
- end
260
-
261
- context 'when uri encoded' do
262
- let(:file_with_double_quote) { Addressable::URI.encode("file://" + Rails.root.join('..', 'spec', 'fixtures', '"file_with_double_quote".mp4').to_s) }
263
-
264
- it "does not have errors" do
265
- sleep 2
266
- expect(find_double_quote_job.errors).to be_empty
267
- end
268
-
269
- it "has the input technical metadata in a file" do
270
- expect(File.read("#{work_dir}/#{create_double_quote_job.id}/input_metadata")).not_to be_empty
271
- end
272
-
273
- it "has the pid in a file" do
274
- expect(File.read("#{work_dir}/#{create_double_quote_job.id}/pid")).not_to be_empty
275
- end
276
- end
277
- end
278
-
279
- context "input filename with other special characters" do
280
- let(:file_with_special_characters) { "file://" + Rails.root.join('..', 'spec', 'fixtures', 'file.with :=+%sp3c!l-ch4cts().mp4').to_s }
281
- let!(:create_special_characters_job) { ActiveEncode::Base.create(file_with_special_characters, outputs: [{ label: "low", ffmpeg_opt: "-s 640x480", extension: 'mp4' }]) }
282
- let(:find_special_characters_job) { ActiveEncode::Base.find create_special_characters_job.id }
283
- let(:file_with_more_special_characters) { "file://" + Rails.root.join('..', 'spec', 'fixtures', '@ወዳጅህ ማር ቢ. ሆን ጨርስ. ህ አትላሰ!@#$^^&$%&.mov').to_s }
284
- let!(:create_more_special_characters_job) { ActiveEncode::Base.create(file_with_more_special_characters, outputs: [{ label: "low", ffmpeg_opt: "-s 640x480", extension: 'mp4' }]) }
285
- let(:find_more_special_characters_job) { ActiveEncode::Base.find create_more_special_characters_job.id }
286
-
287
- it "does not have errors" do
288
- sleep 2
289
- expect(find_special_characters_job.errors).to be_empty
290
- expect(find_more_special_characters_job.errors).to be_empty
291
- end
292
-
293
- it "has the input technical metadata in a file" do
294
- expect(File.read("#{work_dir}/#{create_special_characters_job.id}/input_metadata")).not_to be_empty
295
- expect(File.read("#{work_dir}/#{create_more_special_characters_job.id}/input_metadata")).not_to be_empty
296
- end
297
-
298
- it "has the pid in a file" do
299
- expect(File.read("#{work_dir}/#{create_special_characters_job.id}/pid")).not_to be_empty
300
- expect(File.read("#{work_dir}/#{create_more_special_characters_job.id}/pid")).not_to be_empty
301
- end
302
-
303
- context 'when uri encoded' do
304
- let(:file_with_special_characters) { Addressable::URI.encode("file://" + Rails.root.join('..', 'spec', 'fixtures', 'file.with :=+%sp3c!l-ch4cts().mp4').to_s) }
305
- let(:file_with_more_special_characters) { Addressable::URI.encode("file://" + Rails.root.join('..', 'spec', 'fixtures', '@ወዳጅህ ማር ቢ. ሆን ጨርስ. ህ አትላሰ!@#$^^&$%&.mov').to_s) }
306
-
307
- it "does not have errors" do
308
- sleep 2
309
- expect(find_special_characters_job.errors).to be_empty
310
- expect(find_more_special_characters_job.errors).to be_empty
311
- end
312
-
313
- it "has the input technical metadata in a file" do
314
- expect(File.read("#{work_dir}/#{create_special_characters_job.id}/input_metadata")).not_to be_empty
315
- expect(File.read("#{work_dir}/#{create_more_special_characters_job.id}/input_metadata")).not_to be_empty
316
- end
317
-
318
- it "has the pid in a file" do
319
- expect(File.read("#{work_dir}/#{create_special_characters_job.id}/pid")).not_to be_empty
320
- expect(File.read("#{work_dir}/#{create_more_special_characters_job.id}/pid")).not_to be_empty
321
- end
322
- end
323
- end
324
-
325
- context 'when failed' do
326
- subject { created_job }
327
-
328
- before do
329
- allow_any_instance_of(Object).to receive(:`).and_raise Errno::ENOENT
330
- end
331
-
332
- it { is_expected.to be_failed }
333
- it { expect(subject.errors).to be_present }
334
- end
335
- end
336
-
337
- describe "#find" do
338
- subject { running_job }
339
-
340
- it "has a progress file" do
341
- expect(File).to exist("#{work_dir}/#{subject.id}/progress")
342
- end
343
-
344
- it "does not have an exit code file" do
345
- expect(File).not_to exist("#{work_dir}/#{subject.id}/exit_status.code")
346
- end
347
-
348
- context "completed job" do
349
- subject { completed_job }
350
-
351
- it { is_expected.to be_completed }
352
- it "has an exit code of 0" do
353
- expect(File).to exist("#{work_dir}/#{subject.id}/exit_status.code")
354
- expect(File.read("#{work_dir}/#{subject.id}/exit_status.code").to_i).to eq 0
355
- end
356
- end
357
-
358
- context "completed with warnings job" do
359
- subject { completed_with_warnings_job }
360
-
361
- it { is_expected.to be_completed }
362
- it "has an exit code of 0" do
363
- expect(File).to exist("#{work_dir}/#{subject.id}/exit_status.code")
364
- expect(File.read("#{work_dir}/#{subject.id}/exit_status.code").to_i).to eq 0
365
- end
366
- it "has warnings in the error log" do
367
- expect(File).to exist("#{work_dir}/#{subject.id}/error.log")
368
- expect(File.read("#{work_dir}/#{subject.id}/error.log")).not_to be_empty
369
- end
370
- end
371
-
372
- context "cancelled job" do
373
- subject { canceled_job }
374
-
375
- it { is_expected.to be_cancelled }
376
- it "has an exit code of 143" do
377
- expect(File).to exist("#{work_dir}/#{subject.id}/exit_status.code")
378
- expect(File.read("#{work_dir}/#{subject.id}/exit_status.code").to_i).to eq 143
379
- end
380
- end
381
-
382
- context "failed job" do
383
- subject { failed_job }
384
-
385
- it { is_expected.to be_failed }
386
- it "has an exit code of -22" do
387
- expect(File).to exist("#{work_dir}/#{subject.id}/exit_status.code")
388
- expect(File.read("#{work_dir}/#{subject.id}/exit_status.code").to_i).to eq(-22)
389
- end
390
-
391
- context 'with less than 100 percent completeness' do
392
- subject { incomplete_job }
393
-
394
- it { is_expected.to be_failed }
395
- it 'has an error' do
396
- expect(incomplete_job.errors).to include "Encoding has completed but the output duration is shorter than the input"
397
- end
398
-
399
- it 'succeeds with a configured completeness threshold' do
400
- allow(ActiveEncode::EngineAdapters::FfmpegAdapter).to receive(:completeness_threshold).and_return(95)
401
- expect(incomplete_job).not_to be_failed
402
- expect(incomplete_job.errors).to be_empty
403
- end
404
- end
405
- end
406
- end
407
-
408
- describe "#cancel!" do
409
- subject { running_job }
410
-
411
- it "stops a running process" do
412
- expect(Process).to receive(:kill).with('SIGTERM', running_job.input.id.to_i)
413
- running_job.cancel!
414
- end
415
-
416
- it "does not attempt to stop a non-running encode" do
417
- expect(Process).not_to receive(:kill).with('SIGTERM', completed_job.input.id.to_i)
418
- completed_job.cancel!
419
- end
420
-
421
- it "raises an error if the process can not be found" do
422
- expect(Process).to receive(:kill).with('SIGTERM', running_job.input.id.to_i).and_raise(Errno::ESRCH)
423
- expect { running_job.cancel! }.to raise_error(ActiveEncode::NotRunningError)
424
- end
425
-
426
- it "raises an error" do
427
- expect(Process).to receive(:kill).with('SIGTERM', running_job.input.id.to_i).and_raise(Errno::EPERM)
428
- expect { running_job.cancel! }.to raise_error(ActiveEncode::CancelError)
429
- end
430
- end
431
-
432
- describe "#remove_old_files!" do
433
- subject { created_job }
434
- # 'exit_status.code' and 'progress' seem to be hidden files so rspec does not see them.
435
- # That is why they are not explicitly included in the tests even though they are in the filenames list.
436
- # If they were not being deleted they would cause other tests to fail.
437
- let(:base_path) { "#{work_dir}/#{subject.id}" }
438
- let(:input_metadata_file) { "#{base_path}/input_metadata" }
439
- let(:error_log_file) { "#{base_path}/error.log" }
440
- let(:pid_file) { "#{base_path}/pid" }
441
- let(:exit_status_file) { "#{base_path}/exit_status.code" }
442
- let(:progress_file) { "#{base_path}/progress" }
443
- let(:pathnames) { [input_metadata_file, error_log_file, pid_file, exit_status_file, progress_file] }
444
-
445
- # There was some flaky behavior with the file creation for created_job that
446
- # would cause tests to fail. This ensures the files are created.
447
- before :each do
448
- FileUtils.touch(pathnames)
449
- end
450
-
451
- context ":no_outputs" do
452
- it "deletes files created from encode process older than 2 weeks" do
453
- # Another measure to give files time to be created.
454
- sleep 1
455
- travel 3.weeks do
456
- expect { described_class.remove_old_files! }
457
- .to change { File.exist?(input_metadata_file) }.from(true).to(false)
458
- .and change { File.exist?(error_log_file) }.from(true).to(false)
459
- .and change { File.exist?(pid_file) }.from(true).to(false)
460
- .and not_change { Dir.children("#{work_dir}/#{subject.id}/outputs").count }.from(2)
461
- end
462
- end
463
-
464
- it "does not delete files younger than 2 weeks" do
465
- sleep 1
466
- expect { described_class.remove_old_files! }
467
- .to not_change { File.exist?(input_metadata_file) }.from(true)
468
- .and not_change { File.exist?(error_log_file) }.from(true)
469
- .and not_change { File.exist?(pid_file) }.from(true)
470
- .and not_change { Dir.children("#{work_dir}/#{subject.id}/outputs").count }.from(2)
471
- end
472
- end
473
-
474
- context ":outputs" do
475
- it "deletes outputs created from encode process older than 2 weeks" do
476
- sleep 1
477
- travel 3.weeks do
478
- expect { described_class.remove_old_files!(outputs: true) }
479
- .to not_change { File.exist?(input_metadata_file) }.from(true)
480
- .and not_change { File.exist?(error_log_file) }.from(true)
481
- .and not_change { File.exist?(pid_file) }.from(true)
482
- .and change { Dir.exist?("#{work_dir}/#{subject.id}/outputs") }.from(true).to(false)
483
- end
484
- end
485
-
486
- it "does not delete outputs younger than 2 weeks" do
487
- sleep 1
488
- expect { described_class.remove_old_files!(outputs: true) }
489
- .to not_change { File.exist?(input_metadata_file) }.from(true)
490
- .and not_change { File.exist?(error_log_file) }.from(true)
491
- .and not_change { File.exist?(pid_file) }.from(true)
492
- .and not_change { Dir.children("#{work_dir}/#{subject.id}/outputs").count }.from(2)
493
- end
494
-
495
- it "does not delete outputs directory containing files younger than 2 weeks" do
496
- sleep 1
497
- travel 3.weeks do
498
- allow(File).to receive(:mtime).and_call_original
499
- allow(File).to receive(:mtime).with("#{work_dir}/#{subject.id}/outputs/fireworks-low.mp4").and_return(DateTime.now)
500
- expect { described_class.remove_old_files!(outputs: true) }
501
- .to not_change { Dir.exist?("#{work_dir}/#{subject.id}/outputs") }.from(true)
502
- expect(Dir.children("#{work_dir}/#{subject.id}/outputs")).to eq(["fireworks-low.mp4"])
503
- end
504
- end
505
- end
506
-
507
- context ":all" do
508
- it "deletes all files and directories older than 2 weeks" do
509
- sleep 1
510
- travel 3.weeks do
511
- expect { described_class.remove_old_files!(all: true) }
512
- .to change { Dir.exist?("#{work_dir}/#{subject.id}") }.from(true).to(false)
513
- end
514
- end
515
-
516
- it "does not delete files and directories younger than 2 weeks" do
517
- sleep 1
518
- expect { described_class.remove_old_files!(all: true) }
519
- .to not_change { Dir.exist?("#{work_dir}/#{subject.id}") }.from(true)
520
- .and not_change { Dir.children("#{work_dir}/#{subject.id}").count }
521
- end
522
-
523
- it "does not delete directories containing files younger than 2 weeks" do
524
- sleep 1
525
- travel 3.weeks do
526
- allow(File).to receive(:mtime).and_call_original
527
- allow(File).to receive(:mtime).with("#{work_dir}/#{subject.id}/input_metadata").and_return(DateTime.now)
528
- expect { described_class.remove_old_files!(all: true) }
529
- .to not_change { Dir.exist?("#{work_dir}/#{subject.id}") }.from(true)
530
- expect(Dir.children("#{work_dir}/#{subject.id}")).to eq(["input_metadata"])
531
- end
532
- end
533
- end
534
- end
535
- end
@@ -1,130 +0,0 @@
1
- # frozen_string_literal: true
2
- require 'spec_helper'
3
- require 'rubyhorn'
4
- require 'active_encode/spec/shared_specs'
5
-
6
- describe ActiveEncode::EngineAdapters::MatterhornAdapter do
7
- before(:all) do
8
- Rubyhorn.init(environment: 'test')
9
- ActiveEncode::Base.engine_adapter = :matterhorn
10
- end
11
- after(:all) do
12
- ActiveEncode::Base.engine_adapter = :test
13
- end
14
-
15
- before do
16
- # Stub out all Matterhorn interactions
17
- allow(Rubyhorn).to receive(:client).and_return(double("Rubyhorn::MatterhornClient"))
18
- allow(Rubyhorn.client).to receive(:addMediaPackageWithUrl).and_return(Rubyhorn::Workflow.from_xml(File.open('spec/fixtures/matterhorn/create_response.xml')))
19
- allow(Rubyhorn.client).to receive(:instance_xml).with('running-id').and_return(Rubyhorn::Workflow.from_xml(File.open('spec/fixtures/matterhorn/running_response.xml')))
20
- allow(Rubyhorn.client).to receive(:instance_xml).with('cancelled-id').and_return(Rubyhorn::Workflow.from_xml(File.open('spec/fixtures/matterhorn/cancelled_response.xml')))
21
- allow(Rubyhorn.client).to receive(:instance_xml).with('completed-id').and_return(Rubyhorn::Workflow.from_xml(File.open('spec/fixtures/matterhorn/completed_response.xml')))
22
- allow(Rubyhorn.client).to receive(:instance_xml).with('failed-id').and_return(Rubyhorn::Workflow.from_xml(File.open('spec/fixtures/matterhorn/failed_response.xml')))
23
- allow(Rubyhorn.client).to receive(:stop).and_return(Rubyhorn::Workflow.from_xml(File.open('spec/fixtures/matterhorn/cancelled_response.xml')))
24
- end
25
-
26
- let(:file) { "file://#{File.absolute_path('spec/fixtures/Bars_512kb.mp4')}" }
27
- let(:created_job) { ActiveEncode::Base.create(file) }
28
- let(:running_job) { ActiveEncode::Base.find('running-id') }
29
- let(:canceled_job) { ActiveEncode::Base.find('cancelled-id') }
30
- let(:cancelling_job) { ActiveEncode::Base.find('running-id') }
31
- let(:completed_job) { ActiveEncode::Base.find('completed-id') }
32
- let(:failed_job) { ActiveEncode::Base.find('failed-id') }
33
-
34
- let(:completed_output) { [{ id: "track-7", checksum: "77de9765545ef63d2c21f7557ead6176", duration: 6337, audio_codec: "AAC", audio_bitrate: 76_502.0, video_codec: "AVC", video_bitrate: 2_000_000.0, frame_rate: 30.0, width: 1308, height: 720, url: "file:///home/cjcolvar/Code/avalon/avalon/red5/webapps/avalon/streams/f564d9de-9c35-4b74-95f0-f3013f32cc1a/b09c765f-b64e-4725-a863-736af66b688c/videoshort.mp4", label: "quality-high" }, { id: "track-8", checksum: "10e13cf51bf8a973011eec6a17ea47ff", duration: 6337, audio_codec: "AAC", audio_bitrate: 76_502.0, video_codec: "AVC", video_bitrate: 500_000.0, frame_rate: 30.0, width: 654, height: 360, url: "file:///home/cjcolvar/Code/avalon/avalon/red5/webapps/avalon/streams/f564d9de-9c35-4b74-95f0-f3013f32cc1a/8d5cd8a9-ad0e-484a-96f0-05e26a84a8f0/videoshort.mp4", label: "quality-low" }, { id: "track-9", checksum: "f2b16a2606dc76cb53c7017f0e166204", duration: 6337, audio_codec: "AAC", audio_bitrate: 76_502.0, video_codec: "AVC", video_bitrate: 1_000_000.0, frame_rate: 30.0, width: 872, height: 480, url: "file:///home/cjcolvar/Code/avalon/avalon/red5/webapps/avalon/streams/f564d9de-9c35-4b74-95f0-f3013f32cc1a/0f81d426-0e26-4496-8f58-c675c86e6f4e/videoshort.mp4", label: "quality-medium" }] }
35
- let(:completed_tech_metadata) { {} }
36
- let(:failed_tech_metadata) { { checksum: "7ae24368ccb7a6c6422a14ff73f33c9a", duration: 6314, audio_codec: "AAC", audio_bitrate: 171_030.0, video_codec: "AVC", video_bitrate: 74_477.0, frame_rate: 23.719, width: 200, height: 110 } }
37
- let(:failed_errors) { "org.opencastproject.workflow.api.WorkflowOperationException: org.opencastproject.workflow.api.WorkflowOperationException: One of the encoding jobs did not complete successfully" }
38
-
39
- # Enforce generic behavior
40
- it_behaves_like "an ActiveEncode::EngineAdapter"
41
-
42
- describe "#create" do
43
- subject { created_job }
44
-
45
- it { expect(subject.output).to be_empty }
46
- it { expect(subject.options).to include(preset: 'full') }
47
- end
48
-
49
- describe "#find" do
50
- context "a running encode" do
51
- subject { running_job }
52
-
53
- it { expect(subject.options).to include(preset: 'full') }
54
- it { expect(subject.output).to be_empty }
55
- it { expect(subject.current_operations).to include("Hold for workflow selection") }
56
-
57
- context 'input' do
58
- subject { running_job.input }
59
-
60
- it { expect(subject.width).to be_blank }
61
- it { expect(subject.height).to be_blank }
62
- it { expect(subject.frame_rate).to be_blank }
63
- it { expect(subject.duration).to be_blank }
64
- it { expect(subject.file_size).to be_blank }
65
- it { expect(subject.checksum).to be_blank }
66
- it { expect(subject.audio_codec).to be_blank }
67
- it { expect(subject.video_codec).to be_blank }
68
- it { expect(subject.audio_bitrate).to be_blank }
69
- it { expect(subject.video_bitrate).to be_blank }
70
- end
71
- end
72
- context "a cancelled encode" do
73
- subject { canceled_job }
74
-
75
- it { expect(subject.options).to include(preset: 'full') }
76
- it { expect(subject.current_operations).not_to be_empty }
77
- it { expect(subject.current_operations).to include("Tagging dublin core catalogs for publishing") }
78
- it { expect(subject.updated_at).to be > subject.created_at }
79
- end
80
-
81
- context "a completed encode" do
82
- subject { completed_job }
83
-
84
- it { expect(subject.options).to include(preset: 'avalon') }
85
- it { expect(subject.current_operations).to include("Cleaning up") }
86
- end
87
- context "a failed encode" do
88
- subject { failed_job }
89
-
90
- it { expect(subject.options).to include(preset: 'error') }
91
- it { expect(subject.current_operations).to include("Cleaning up after failure") }
92
- end
93
- end
94
-
95
- describe "#cancel!" do
96
- subject { encode.cancel! }
97
- let(:encode) { ActiveEncode::Base.create(file) }
98
-
99
- it { is_expected.to be_a ActiveEncode::Base }
100
- it { expect(subject.id).to eq 'cancelled-id' }
101
- it { is_expected.to be_cancelled }
102
- end
103
-
104
- describe "reload" do
105
- subject { running_job.reload }
106
- before do
107
- expect(Rubyhorn.client).to receive(:instance_xml).twice.with('running-id').and_return(Rubyhorn::Workflow.from_xml(File.open('spec/fixtures/matterhorn/running_response.xml')))
108
- end
109
-
110
- it { expect(subject.output).to be_empty }
111
- it { expect(subject.options).to include(preset: 'full') }
112
- it { expect(subject.current_operations).to include("Hold for workflow selection") }
113
- it { expect(subject.percent_complete).to eq 0.43478260869565216 }
114
-
115
- context 'input' do
116
- subject { running_job.reload.input }
117
-
118
- it { expect(subject.width).to be_blank }
119
- it { expect(subject.height).to be_blank }
120
- it { expect(subject.frame_rate).to be_blank }
121
- it { expect(subject.duration).to be_blank }
122
- it { expect(subject.file_size).to be_blank }
123
- it { expect(subject.checksum).to be_blank }
124
- it { expect(subject.audio_codec).to be_blank }
125
- it { expect(subject.video_codec).to be_blank }
126
- it { expect(subject.audio_bitrate).to be_blank }
127
- it { expect(subject.video_bitrate).to be_blank }
128
- end
129
- end
130
- end