jam-cloud/ruby/spec/jam_ruby/models/quick_mix_spec.rb

213 lines
8.7 KiB
Ruby

require 'spec_helper'
require 'rest-client'
describe QuickMix do
include UsesTempFiles
before do
@user = FactoryBot.create(:user)
@connection = FactoryBot.create(:connection, :user => @user)
@instrument = FactoryBot.create(:instrument, :description => 'a great instrument')
@music_session = FactoryBot.create(:active_music_session, :creator => @user, :musician_access => true)
@track = FactoryBot.create(:track, :connection => @connection, :instrument => @instrument)
@recording = FactoryBot.create(:recording, :music_session => @music_session, :owner => @user)
end
it "should copy from a regular track properly" do
@quick_mix = QuickMix.create(@recording, @user)
@quick_mix.user.id.should == @track.connection.user.id
@quick_mix.next_part_to_upload.should == 0
@quick_mix.fully_uploaded.should == false
end
it "should update the next part to upload properly" do
@quick_mix = QuickMix.create(@recording, @user)
@quick_mix.upload_part_complete(1, 1000)
@quick_mix.errors.any?.should be true
@quick_mix.errors[:ogg_length][0].should == "is too short (minimum is 1 character)"
@quick_mix.errors[:ogg_md5][0].should == "can't be blank"
end
it "gets a url for the track" do
@quick_mix = QuickMix.create(@recording, @user)
@quick_mix.errors.any?.should be false
@quick_mix[:ogg_url].should == "recordings/#{@recording.created_at.strftime('%m-%d-%Y')}/#{@recording.id}/stream-mix-#{@quick_mix.id}.ogg"
@quick_mix[:mp3_url].should == "recordings/#{@recording.created_at.strftime('%m-%d-%Y')}/#{@recording.id}/stream-mix-#{@quick_mix.id}.mp3"
end
it "signs url" do
stub_const("APP_CONFIG", app_config)
@quick_mix = QuickMix.create(@recording, @user)
@quick_mix.sign_url.should_not be_nil
end
describe "aws-based operations", :aws => true do
def put_file_to_aws(signed_data, contents)
begin
RestClient.put( signed_data[:url],
contents,
{
:'Content-Type' => 'audio/ogg',
:Date => signed_data[:datetime],
:'Content-MD5' => signed_data[:md5],
:Authorization => signed_data[:authorization]
})
rescue => e
puts e.response
raise e
end
end
# create a test file
upload_file='some_file.ogg'
in_directory_with_file(upload_file)
upload_file_contents="ogg binary stuff in here"
md5 = Base64.encode64(Digest::MD5.digest(upload_file_contents)).chomp
test_config = app_config
s3_manager = S3Manager.new(test_config.aws_bucket, test_config.aws_access_key_id, test_config.aws_secret_access_key)
before do
stub_const("APP_CONFIG", app_config)
# this block of code will fully upload a sample file to s3
content_for_file(upload_file_contents)
s3_manager.delete_folder('recordings') # keep the bucket clean to save cost, and make it easier if post-mortuem debugging
end
it "cant mark a part complete without having started it" do
@quick_mix = QuickMix.create(@recording, @user)
@quick_mix.upload_start(1000, "abc")
@quick_mix.upload_part_complete(1, 1000)
@quick_mix.errors.any?.should be true
@quick_mix.errors[:next_part_to_upload][0].should == ValidationMessages::PART_NOT_STARTED
end
it "no parts" do
@quick_mix = QuickMix.create(@recording, @user)
@quick_mix.upload_start(1000, "abc")
@quick_mix.upload_next_part(1000, "abc")
@quick_mix.errors.any?.should be false
@quick_mix.upload_part_complete(1, 1000)
@quick_mix.errors.any?.should be true
@quick_mix.errors[:next_part_to_upload][0].should == ValidationMessages::PART_NOT_FOUND_IN_AWS
end
it "enough part failures reset the upload" do
@quick_mix = QuickMix.create(@recording, @user)
@quick_mix.upload_start(File.size(upload_file), md5)
@quick_mix.upload_next_part(File.size(upload_file), md5)
@quick_mix.errors.any?.should be false
APP_CONFIG.max_track_part_upload_failures.times do |i|
@quick_mix.upload_part_complete(@quick_mix.next_part_to_upload, File.size(upload_file))
@quick_mix.errors[:next_part_to_upload] == [ValidationMessages::PART_NOT_FOUND_IN_AWS]
part_failure_rollover = i == APP_CONFIG.max_track_part_upload_failures - 1
expected_is_part_uploading = !part_failure_rollover
expected_part_failures = part_failure_rollover ? 0 : i + 1
@quick_mix.reload
@quick_mix.is_part_uploading.should == expected_is_part_uploading
@quick_mix.part_failures.should == expected_part_failures
end
@quick_mix.reload
@quick_mix.upload_failures.should == 1
@quick_mix.file_offset.should == 0
@quick_mix.next_part_to_upload.should == 0
@quick_mix.upload_id.should be_nil
@quick_mix.ogg_md5.should be_nil
@quick_mix.ogg_length.should == 0
end
it "enough upload failures fails the upload forever" do
APP_CONFIG.stub(:max_track_upload_failures).and_return(1)
APP_CONFIG.stub(:max_track_part_upload_failures).and_return(2)
@quick_mix = QuickMix.create(@recording, @user)
APP_CONFIG.max_track_upload_failures.times do |j|
@quick_mix.upload_start(File.size(upload_file), md5)
@quick_mix.upload_next_part(File.size(upload_file), md5)
@quick_mix.errors.any?.should be false
APP_CONFIG.max_track_part_upload_failures.times do |i|
@quick_mix.upload_part_complete(@quick_mix.next_part_to_upload, File.size(upload_file))
@quick_mix.errors[:next_part_to_upload] == [ValidationMessages::PART_NOT_FOUND_IN_AWS]
part_failure_rollover = i == APP_CONFIG.max_track_part_upload_failures - 1
expected_is_part_uploading = part_failure_rollover ? false : true
expected_part_failures = part_failure_rollover ? 0 : i + 1
@quick_mix.reload
@quick_mix.is_part_uploading.should == expected_is_part_uploading
@quick_mix.part_failures.should == expected_part_failures
end
@quick_mix.upload_failures.should == j + 1
end
@quick_mix.reload
@quick_mix.upload_failures.should == APP_CONFIG.max_track_upload_failures
@quick_mix.file_offset.should == 0
@quick_mix.next_part_to_upload.should == 0
@quick_mix.upload_id.should be_nil
@quick_mix.ogg_md5.should be_nil
@quick_mix.ogg_length.should == 0
# try to poke it and get the right kind of error back
@quick_mix.upload_next_part(File.size(upload_file), md5)
@quick_mix.errors[:upload_failures] = [ValidationMessages::UPLOAD_FAILURES_EXCEEDED]
end
describe "correctly uploaded a file" do
before do
@quick_mix = QuickMix.create(@recording, @user)
@quick_mix.upload_start(File.size(upload_file), md5)
@quick_mix.upload_next_part(File.size(upload_file), md5)
signed_data = @quick_mix.upload_sign(md5)
@response = put_file_to_aws(signed_data, upload_file_contents)
@quick_mix.upload_part_complete(@quick_mix.next_part_to_upload, File.size(upload_file))
@quick_mix.errors.any?.should be false
@quick_mix.upload_complete
@quick_mix.marking_complete = false # this is a side effect of using the same model throughout this process; controllers wouldn't see this
@quick_mix.finish(File.size(upload_file), md5)
@quick_mix.errors.any?.should be false
# let's verify that .finish sets everything it should
@quick_mix.mp3_length.should == File.size(upload_file)
@quick_mix.mp3_md5.should == md5
@quick_mix.completed.should be true
@quick_mix.recording.reload
@quick_mix.recording.first_quick_mix_id.should == @quick_mix.id
end
it "can download an updated file" do
@response = RestClient.get @quick_mix.sign_url
@response.body.should == upload_file_contents
end
it "can't mark completely uploaded twice" do
@quick_mix.upload_complete
@quick_mix.errors.any?.should be true
@quick_mix.errors[:fully_uploaded][0].should == "already set"
@quick_mix.part_failures.should == 0
end
it "can't ask for a next part if fully uploaded" do
@quick_mix.upload_next_part(File.size(upload_file), md5)
@quick_mix.errors.any?.should be true
@quick_mix.errors[:fully_uploaded][0].should == "already set"
@quick_mix.part_failures.should == 0
end
it "can't ask for mark part complete if fully uploaded" do
@quick_mix.upload_part_complete(1, 1000)
@quick_mix.errors.any?.should be true
@quick_mix.errors[:fully_uploaded][0].should == "already set"
@quick_mix.part_failures.should == 0
end
end
end
end