2014-10-23 04:10:49 +00:00
|
|
|
require 'spec_helper'
|
|
|
|
|
require 'rest-client'
|
|
|
|
|
|
|
|
|
|
describe QuickMix do
|
|
|
|
|
|
|
|
|
|
include UsesTempFiles
|
|
|
|
|
|
|
|
|
|
before do
|
|
|
|
|
@user = FactoryGirl.create(:user)
|
|
|
|
|
@connection = FactoryGirl.create(:connection, :user => @user)
|
|
|
|
|
@instrument = FactoryGirl.create(:instrument, :description => 'a great instrument')
|
|
|
|
|
@music_session = FactoryGirl.create(:active_music_session, :creator => @user, :musician_access => true)
|
|
|
|
|
@track = FactoryGirl.create(:track, :connection => @connection, :instrument => @instrument)
|
|
|
|
|
@recording = FactoryGirl.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
|
2016-07-17 15:16:27 +00:00
|
|
|
@quick_mix.errors[:ogg_length][0].should == "is too short (minimum is 1 character)"
|
2014-10-23 04:10:49 +00:00
|
|
|
@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
|
|
|
|
|
|