typingpool 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (90) hide show
  1. data/Rakefile +23 -0
  2. data/bin/tp-assign +240 -0
  3. data/bin/tp-collect +50 -0
  4. data/bin/tp-config +114 -0
  5. data/bin/tp-finish +101 -0
  6. data/bin/tp-make +169 -0
  7. data/bin/tp-review +175 -0
  8. data/lib/typingpool/amazon.rb +732 -0
  9. data/lib/typingpool/app.rb +634 -0
  10. data/lib/typingpool/config.rb +344 -0
  11. data/lib/typingpool/error.rb +22 -0
  12. data/lib/typingpool/filer.rb +396 -0
  13. data/lib/typingpool/project.rb +593 -0
  14. data/lib/typingpool/template.rb +175 -0
  15. data/lib/typingpool/templates/assignment/amazon-init.js +38 -0
  16. data/lib/typingpool/templates/assignment/interview/nameless.html.erb +13 -0
  17. data/lib/typingpool/templates/assignment/interview/noisy.html.erb +12 -0
  18. data/lib/typingpool/templates/assignment/interview/partials/voices.html.erb +10 -0
  19. data/lib/typingpool/templates/assignment/interview/phone.html.erb +12 -0
  20. data/lib/typingpool/templates/assignment/interview.html.erb +11 -0
  21. data/lib/typingpool/templates/assignment/main.css +20 -0
  22. data/lib/typingpool/templates/assignment/partials/entry.html.erb +19 -0
  23. data/lib/typingpool/templates/assignment/partials/footer.html.erb +3 -0
  24. data/lib/typingpool/templates/assignment/partials/header.html.erb +11 -0
  25. data/lib/typingpool/templates/assignment/partials/labeling-example.html.erb +4 -0
  26. data/lib/typingpool/templates/assignment/partials/labeling.html.erb +5 -0
  27. data/lib/typingpool/templates/assignment/partials/length-description.html.erb +6 -0
  28. data/lib/typingpool/templates/assignment/partials/voices.html.erb +10 -0
  29. data/lib/typingpool/templates/assignment/speech.html.erb +11 -0
  30. data/lib/typingpool/templates/config.yml +21 -0
  31. data/lib/typingpool/templates/project/audio/chunks/.empty_directory +0 -0
  32. data/lib/typingpool/templates/project/audio/originals/.empty_directory +0 -0
  33. data/lib/typingpool/templates/project/data/.empty_directory +0 -0
  34. data/lib/typingpool/templates/project/etc/ About these files - read me.txt +8 -0
  35. data/lib/typingpool/templates/project/etc/audio-compat.js +25 -0
  36. data/lib/typingpool/templates/project/etc/player/audio-player.js +4 -0
  37. data/lib/typingpool/templates/project/etc/player/license.txt +19 -0
  38. data/lib/typingpool/templates/project/etc/player/player.swf +0 -0
  39. data/lib/typingpool/templates/project/etc/transcript.css +49 -0
  40. data/lib/typingpool/templates/transcript.html.erb +23 -0
  41. data/lib/typingpool/test/fixtures/amazon-question-html.html +95 -0
  42. data/lib/typingpool/test/fixtures/amazon-question-url.txt +1 -0
  43. data/lib/typingpool/test/fixtures/audio/mp3/interview.1.mp3 +0 -0
  44. data/lib/typingpool/test/fixtures/audio/mp3/interview.2.mp3 +0 -0
  45. data/lib/typingpool/test/fixtures/audio/wma/VN620007.WMA +0 -0
  46. data/lib/typingpool/test/fixtures/audio/wma/VN620052.WMA +0 -0
  47. data/lib/typingpool/test/fixtures/config-1 +20 -0
  48. data/lib/typingpool/test/fixtures/config-2 +25 -0
  49. data/lib/typingpool/test/fixtures/not_yaml.txt +4 -0
  50. data/lib/typingpool/test/fixtures/template-2.html.erb +10 -0
  51. data/lib/typingpool/test/fixtures/template-3.html.erb +22 -0
  52. data/lib/typingpool/test/fixtures/template.html.erb +10 -0
  53. data/lib/typingpool/test/fixtures/tp_collect_id.txt +1 -0
  54. data/lib/typingpool/test/fixtures/tp_collect_sandbox-assignment.csv +8 -0
  55. data/lib/typingpool/test/fixtures/tp_review_id.txt +1 -0
  56. data/lib/typingpool/test/fixtures/tp_review_sandbox-assignment.csv +8 -0
  57. data/lib/typingpool/test/fixtures/transcript-chunks.csv +226 -0
  58. data/lib/typingpool/test/fixtures/utf8_transcript.txt +7 -0
  59. data/lib/typingpool/test/fixtures/vcr/tp-collect-1.yml +2712 -0
  60. data/lib/typingpool/test/fixtures/vcr/tp-collect-2.yml +2718 -0
  61. data/lib/typingpool/test/fixtures/vcr/tp-collect-3.yml +2768 -0
  62. data/lib/typingpool/test/fixtures/vcr/tp-review-1.yml +570 -0
  63. data/lib/typingpool/test/fixtures/vcr/tp-review-2.yml +351 -0
  64. data/lib/typingpool/test.rb +418 -0
  65. data/lib/typingpool/transcript.rb +181 -0
  66. data/lib/typingpool/utility.rb +272 -0
  67. data/lib/typingpool.rb +500 -0
  68. data/test/make_amazon_question_fixture.rb +24 -0
  69. data/test/make_tp_collect_fixture_1.rb +26 -0
  70. data/test/make_tp_collect_fixture_2.rb +16 -0
  71. data/test/make_tp_collect_fixture_3.rb +15 -0
  72. data/test/make_tp_collect_fixture_4.rb +17 -0
  73. data/test/make_tp_review_fixture_1.rb +26 -0
  74. data/test/make_tp_review_fixture_2.rb +30 -0
  75. data/test/make_transcript_chunks_fixture.rb +53 -0
  76. data/test/test_integration_script_1_tp_config.rb +108 -0
  77. data/test/test_integration_script_2_tp_make.rb +119 -0
  78. data/test/test_integration_script_3_tp_assign.rb +152 -0
  79. data/test/test_integration_script_4_tp_review.rb +72 -0
  80. data/test/test_integration_script_5_tp_collect.rb +44 -0
  81. data/test/test_integration_script_6_tp_finish.rb +123 -0
  82. data/test/test_unit_amazon.rb +153 -0
  83. data/test/test_unit_config.rb +94 -0
  84. data/test/test_unit_filer.rb +202 -0
  85. data/test/test_unit_project.rb +168 -0
  86. data/test/test_unit_project_local.rb +68 -0
  87. data/test/test_unit_project_remote.rb +157 -0
  88. data/test/test_unit_template.rb +111 -0
  89. data/test/test_unit_transcript.rb +77 -0
  90. metadata +234 -0
@@ -0,0 +1,53 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ $:.unshift File.join(File.dirname(File.dirname($0)), 'lib')
4
+
5
+ require 'typingpool'
6
+
7
+ lines_each = 2
8
+ if ARGV.last.to_s.match(/^\d+$/)
9
+ lines_each = ARGV.pop.to_i
10
+ end
11
+
12
+ if ARGV.empty?
13
+ abort "USAGE: #{File.basename($PROGRAM_NAME)} PROJECT_DIR [PROJECT_DIR...] [LINES_EACH=2]"
14
+ end
15
+
16
+ data_files = ARGV.map do |path|
17
+ data_file = nil
18
+ expanded = File.expand_path(path)
19
+ if not(File.exists? expanded)
20
+ abort "No such dir #{path}"
21
+ end
22
+ if not(File.directory? expanded)
23
+ abort "Not a dir: #{path}"
24
+ end
25
+ %w(data csv).each do |data_dir_name|
26
+ possible_data_file = File.join(expanded, data_dir_name, 'assignment.csv')
27
+ if File.exists? possible_data_file
28
+ data_file = possible_data_file
29
+ end
30
+ end #%w().each do...
31
+ if not(data_file)
32
+ abort "Dir #{path} has no data/assignment.csv or csv/assignment.csv"
33
+ end
34
+ data_file
35
+ end #ARGV.map
36
+
37
+ assignments=[]
38
+ data_files.each do |path|
39
+ csv = Typingpool::Filer::CSV.new(path)
40
+ with_transcripts = csv.reject{|assignment| assignment['transcript'].to_s.empty? }
41
+ next if with_transcripts.empty?
42
+ seeking = with_transcripts.count
43
+ if seeking > lines_each
44
+ seeking = lines_each
45
+ end
46
+ assignments.push(*with_transcripts.sample(seeking))
47
+ end #data_files.each do...
48
+
49
+ if assignments.empty?
50
+ abort "No transcripts found"
51
+ end
52
+ fixtures_dir = File.join(Typingpool::Utility.lib_dir, 'test', 'fixtures')
53
+ Typingpool::Filer::CSV.new(File.join(fixtures_dir, 'transcript-chunks.csv')).write(assignments)
@@ -0,0 +1,108 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ $:.unshift File.join(File.dirname(File.dirname($0)), 'lib')
4
+
5
+ require 'typingpool'
6
+ require 'typingpool/test'
7
+
8
+ class TestTpConfig < Typingpool::Test::Script
9
+
10
+ def test_abort_with_invalid_file
11
+ exception = assert_raise(Typingpool::Error::Shell) do
12
+ tp_config(File.join(fixtures_dir, 'not_yaml.txt'))
13
+ end
14
+ assert_match(exception.message, /not valid yaml/i)
15
+ end
16
+
17
+ def test_abort_with_directory_path
18
+ dir = File.join(fixtures_dir, 'vcr')
19
+ assert(File.exists? dir)
20
+ assert(File.directory? dir)
21
+ exception = assert_raise(Typingpool::Error::Shell) do
22
+ tp_config(dir)
23
+ end
24
+ assert_match(exception.message, /not a file/i)
25
+ end
26
+
27
+ def test_abort_with_invalid_path
28
+ path = '/jksdljs/euwiroeuw'
29
+ refute(File.exists? path)
30
+ exception = assert_raise(Typingpool::Error::Shell) do
31
+ tp_config(path)
32
+ end
33
+ assert_match(exception.message, /valid path/i)
34
+ end
35
+
36
+ def test_usage_message
37
+ assert(output = tp_config('--help'))
38
+ assert_match(output, /\bUSAGE:/)
39
+ end
40
+
41
+ def test_new_config_creation
42
+ in_temp_dir do |dir|
43
+ path = {
44
+ :config => File.join(dir, 'config.yml'),
45
+ :transcript_dir => File.join(dir, 'transcriptionz')
46
+ }
47
+ path.values.each{|path| refute(File.exists? path) }
48
+ assert(output = tp_config_with_input([path[:config], '--test'], ['keykey', 'secretsecret', path[:transcript_dir]]))
49
+ assert_match(output[:err], /wrote config to/i)
50
+ path.values.each{|path| assert(File.exists? path) }
51
+ assert(File.file? path[:config] )
52
+ assert(File.directory? path[:transcript_dir] )
53
+ assert(config = Typingpool::Config.file(path[:config]))
54
+ assert_equal(path[:transcript_dir], config.transcripts)
55
+ assert_equal(File.join(path[:transcript_dir], 'templates').downcase, config.templates.downcase)
56
+ assert_equal('keykey', config.amazon.key)
57
+ assert_equal('secretsecret', config.amazon.secret)
58
+ refute_empty(config.amazon.bucket.to_s)
59
+ end #in_temp_dir do |dir|
60
+ end
61
+
62
+ def test_config_editing
63
+ in_temp_dir do |dir|
64
+ path = {
65
+ :config => File.join(dir, 'config.yml'),
66
+ :fixture => File.join(fixtures_dir, 'config-1'),
67
+ :transcript_dir => File.join(dir, 'transcriptionz')
68
+ }
69
+ assert(File.exists? path[:fixture])
70
+ refute(File.exists? path[:config])
71
+ FileUtils.cp(path[:fixture], path[:config])
72
+ assert(File.exists? path[:config])
73
+ assert(original_config = Typingpool::Config.file(path[:config]))
74
+ [:key, :secret, :bucket].each{|param| refute_empty(original_config.amazon.send(param).to_s) }
75
+ [:transcripts, :templates, :cache].each{|param| refute_empty(original_config.send(param).to_s) }
76
+ assert(output = tp_config_with_input([path[:config], '--test'], ['keykey', 'secretsecret', path[:transcript_dir]]))
77
+ assert(edited_config = Typingpool::Config.file(path[:config]))
78
+ [:key, :secret].each{|param| refute_equal(original_config.amazon.send(param), edited_config.amazon.send(param)) }
79
+ assert_equal(original_config.amazon.bucket, edited_config.amazon.bucket)
80
+ [:templates, :cache].each{|param| assert_equal(original_config.send(param), edited_config.send(param)) }
81
+ refute_equal(original_config.transcripts, edited_config.transcripts)
82
+ assert_equal('keykey', edited_config.amazon.key)
83
+ assert_equal('secretsecret', edited_config.amazon.secret)
84
+ assert_equal(path[:transcript_dir], edited_config.transcripts)
85
+ end #in_temp_dir |dir| do
86
+ end
87
+
88
+ def test_skips_bucket_when_sftp_params_exist
89
+ in_temp_dir do |dir|
90
+ path = {
91
+ :config => File.join(dir, 'config.yml'),
92
+ :fixture => File.join(fixtures_dir, 'config-2'),
93
+ :transcript_dir => File.join(dir, 'transcriptionz')
94
+ }
95
+ assert(File.exists? path[:fixture])
96
+ refute(File.exists? path[:config])
97
+ FileUtils.cp(path[:fixture], path[:config])
98
+ assert(File.exists? path[:config])
99
+ assert(original_config = Typingpool::Config.file(path[:config]))
100
+ assert_empty(original_config.amazon.bucket.to_s)
101
+ assert(output = tp_config_with_input([path[:config], '--test'], ['keykey', 'secretsecret', path[:transcript_dir]]))
102
+ assert_match(output[:err], /wrote config to/i)
103
+ assert(edited_config = Typingpool::Config.file(path[:config]))
104
+ assert_empty(edited_config.amazon.bucket.to_s)
105
+ end #in_temp_dir do |dir|
106
+ end
107
+
108
+ end #class TestTpConfig
@@ -0,0 +1,119 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ $:.unshift File.join(File.dirname(File.dirname($0)), 'lib')
4
+
5
+ require 'typingpool'
6
+ require 'typingpool/test'
7
+ require 'csv'
8
+
9
+ class TestTpMake < Typingpool::Test::Script
10
+ def test_abort_with_no_files
11
+ assert_tp_make_abort_match(['--title', 'Foo', '--chunks', '0:20'], /no files/i)
12
+ end
13
+
14
+ def test_abort_with_no_title
15
+ assert_tp_make_abort_match(['--file', audio_files[0]], /no title/i)
16
+ end
17
+
18
+ def test_abort_with_invalid_title
19
+ assert_tp_make_abort_match(['--file', audio_files[0], '--title', 'Foo/Bar'], /illegal character/i)
20
+ end
21
+
22
+ def test_abort_with_no_args
23
+ assert_tp_make_abort_match([], /\bUSAGE:/)
24
+ end
25
+
26
+ def assert_tp_make_abort_match(args, regex)
27
+ assert_script_abort_match(args, regex) do |args|
28
+ call_tp_make(*args)
29
+ end
30
+ end
31
+
32
+ def tp_make_with(dir, config_path, subdir='mp3')
33
+ begin
34
+ tp_make(dir, config_path, subdir)
35
+ assert(project = temp_tp_dir_project(dir, Typingpool::Config.file(config_path)))
36
+ assert_not_nil(project.local)
37
+ assert_not_nil(project.local.id)
38
+ assert(project.local.subdir('audio','chunks').to_a.size <= 7)
39
+ assert(project.local.subdir('audio','chunks').to_a.size >= 6)
40
+ assert_equal(project_default[:subtitle], project.local.subtitle)
41
+ assignments = project.local.file('data', 'assignment.csv').as(:csv)
42
+ assert_equal(project.local.subdir('audio','chunks').to_a.size, assignments.count)
43
+ assert_all_assets_have_upload_status(assignments, ['audio'], 'yes')
44
+ assignments.each do |assignment|
45
+ assert_not_nil(assignment['audio_url'])
46
+ assert(working_url? assignment['audio_url'])
47
+ assert_equal(assignment['project_id'], project.local.id)
48
+ assert_equal(assignment['unusual'].split(/\s*,\s*/), project_default[:unusual])
49
+ project_default[:voice].each_with_index do |voice, i|
50
+ name, description = voice.split(/\s*,\s*/)
51
+ assert_equal(name, assignment["voice#{i+1}"])
52
+ if not(description.to_s.empty?)
53
+ assert_equal(description, assignment["voice#{i+1}title"])
54
+ end
55
+ end #project_default[:voice].each_with_index...
56
+ end #assignments.each d0....
57
+ ensure
58
+ tp_finish_outside_sandbox(dir, config_path)
59
+ end #begin
60
+ assert_all_assets_have_upload_status(assignments, ['audio'], 'no')
61
+ end
62
+
63
+ def test_tp_make
64
+ Dir.entries(audio_dir).select{|entry| File.directory?(File.join(audio_dir, entry))}.reject{|entry| entry.match(/^\./) }.each do |subdir|
65
+ in_temp_tp_dir do |dir|
66
+ config_path = self.config_path(dir)
67
+ skip_if_no_upload_credentials('tp-make integration test', Typingpool::Config.file(config_path))
68
+ tp_make_with(dir, config_path, subdir)
69
+ end #in_temp_tp_dir
70
+ end #Dir.entries
71
+ end
72
+
73
+ def test_tp_make_s3
74
+ in_temp_tp_dir do |dir|
75
+ skip_if_no_s3_credentials('tp-make S3 integration test', config)
76
+ config_path = setup_s3_config(dir)
77
+ tp_make_with(dir, config_path)
78
+ end #in_temp_tp_dir do...
79
+ end
80
+
81
+ def test_fixing_failed_tp_make
82
+ in_temp_tp_dir do |dir|
83
+ config = config_from_dir(dir)
84
+ skip_if_no_s3_credentials('tp-make failed upload integration test', config)
85
+ good_config_path = setup_s3_config(dir)
86
+ bad_config_path = setup_s3_config_with_bad_password(dir)
87
+ assert_raises(Typingpool::Error::Shell) do
88
+ tp_make(dir, bad_config_path, 'mp3')
89
+ end
90
+ project_dir = temp_tp_dir_project_dir(dir)
91
+ assert(File.exists? project_dir)
92
+ assert(File.directory? project_dir)
93
+ assert(File.exists? File.join(project_dir, 'data', 'assignment.csv'))
94
+ originals_dir = File.join(project_dir, 'audio', 'originals')
95
+ refute_empty(Dir.entries(originals_dir).reject{|entry| entry.match(/^\./) }.map{|entry| File.join(originals_dir, entry) }.select{|path| File.file? path })
96
+ assert(project = temp_tp_dir_project(dir))
97
+ assert(assignment_csv = project.local.file('data', 'assignment.csv').as(:csv))
98
+ refute_empty(assignment_csv.to_a)
99
+ assert_all_assets_have_upload_status(assignment_csv, ['audio'], 'maybe')
100
+ assert(audio_urls = assignment_csv.map{|assignment| assignment['audio_url'] })
101
+ refute_empty(audio_urls)
102
+ assert_empty(audio_urls.select{|url| working_url? url })
103
+ begin
104
+ tp_make(dir, good_config_path, 'mp3')
105
+ refute_empty(assignment_csv.read)
106
+ assert_all_assets_have_upload_status(assignment_csv, ['audio'], 'yes')
107
+ refute_empty(audio_urls2 = assignment_csv.map{|assignment| assignment['audio_url'] })
108
+ audio_urls.each_with_index do |original_url, i|
109
+ assert_equal(original_url, audio_urls2[i])
110
+ end
111
+ assert_equal(audio_urls.count, audio_urls2.select{|url| working_url? url }.count)
112
+ ensure
113
+ tp_finish_outside_sandbox(dir, good_config_path)
114
+ end #begin
115
+ assert_all_assets_have_upload_status(assignment_csv, ['audio'], 'no')
116
+ end #in_temp_tp_dir do...
117
+ end
118
+
119
+ end #TestTpMake
@@ -0,0 +1,152 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ $:.unshift File.join(File.dirname(File.dirname($0)), 'lib')
4
+
5
+ require 'typingpool'
6
+ require 'typingpool/test'
7
+
8
+ class TestTpAssign < Typingpool::Test::Script
9
+ #TODO: test that qualifications are sent (will need heroic effort
10
+ #(or at least some xml parsing) since rturk doesn't provide an
11
+ #easy way to look at HIT qualifications)
12
+ def test_abort_with_no_input
13
+ assert_raise(Typingpool::Error::Shell){call_tp_assign}
14
+ end
15
+
16
+ def test_abort_with_no_template
17
+ assert_tp_assign_abort_match([project_default[:title]], /Missing\b[^\n\r\f]*\btemplate/i)
18
+ end
19
+
20
+ def test_abort_with_bad_timespec
21
+ assert_tp_assign_abort_match([project_default[:title], assign_default[:template], '--lifetime', '4u'], /can't convert/i)
22
+ end
23
+
24
+ def test_abort_with_bad_qualification
25
+ assert_tp_assign_abort_match([project_default[:title], assign_default[:template], '--qualify', 'approval_rate &= 8'], /\bsense of --qualify.+\bunknown comparator\b/i)
26
+ assert_tp_assign_abort_match([project_default[:title], assign_default[:template], '--qualify', 'fake_rate > 8'], /\bsense of --qualify\b.+unknown\b[^\n\r\f]*\btype\b/i)
27
+ end
28
+
29
+ def test_abort_with_bad_reward
30
+ assert_tp_assign_abort_match([project_default[:title], assign_default[:template], '--reward', 'foo'], /sense of --reward/i)
31
+ end
32
+
33
+ def assert_tp_assign_abort_match(args, regex)
34
+ assert_script_abort_match(args, regex) do |args|
35
+ call_tp_assign(*args)
36
+ end
37
+ end
38
+
39
+ def test_tp_assign
40
+ skip_if_no_amazon_credentials('tp-assign integration test')
41
+ skip_if_no_upload_credentials('tp-assign integration test')
42
+ in_temp_tp_dir do |dir|
43
+ tp_make(dir)
44
+ begin
45
+ tp_assign(dir)
46
+ assign_time = Time.now
47
+ config = config_from_dir(dir)
48
+ project = temp_tp_dir_project(dir)
49
+ setup_amazon(dir)
50
+ results = nil
51
+ refute_empty(results = Typingpool::Amazon::HIT.all_for_project(project.local.id))
52
+ assert_equal(project.local.subdir('audio','chunks').to_a.size, results.size)
53
+ assert_equal(Typingpool::Utility.timespec_to_seconds(assign_default[:deadline]), results[0].full.assignments_duration.to_i)
54
+ #These numbers will be apart due to clock differences and
55
+ #timing vagaries of the assignment.
56
+ assert_in_delta((assign_time + Typingpool::Utility.timespec_to_seconds(assign_default[:lifetime])).to_f, results[0].full.expires_at.to_f, 60)
57
+ keywords = results[0].at_amazon.keywords
58
+ assign_default[:keyword].each{|keyword| assert_includes(keywords, keyword)}
59
+ sandbox_csv = project.local.file('data', 'sandbox-assignment.csv').as(:csv)
60
+ refute_empty(assignment_urls = sandbox_csv.map{|assignment| assignment['assignment_url'] })
61
+ assert(assignment_html = fetch_url(assignment_urls.first).body)
62
+ assert_match(assignment_html, /\b20[\s-]+second\b/)
63
+ assert_all_assets_have_upload_status(sandbox_csv, ['assignment'], 'yes')
64
+ ensure
65
+ tp_finish(dir)
66
+ end #begin
67
+ assert_empty(Typingpool::Amazon::HIT.all_for_project(project.local.id))
68
+ end # in_temp_tp_dir
69
+ end
70
+
71
+ def test_uploads_audio_when_needed
72
+ skip_if_no_amazon_credentials('tp-assign unuploaded audio integration test')
73
+ skip_if_no_s3_credentials('tp-assign unuploaded audio integration test')
74
+ in_temp_tp_dir do |dir|
75
+ good_config_path = setup_s3_config(dir)
76
+ bad_config_path = setup_s3_config_with_bad_password(dir)
77
+ assert_raises(Typingpool::Error::Shell) do
78
+ tp_make(dir, bad_config_path, 'mp3')
79
+ end
80
+ project_dir = temp_tp_dir_project_dir(dir)
81
+ assert(File.exists? project_dir)
82
+ assert(File.directory? project_dir)
83
+ assert(project = temp_tp_dir_project(dir, Typingpool::Config.file(bad_config_path)))
84
+ csv = project.local.file('data', 'assignment.csv').as(:csv)
85
+ assert_empty(csv.select{|assignment| working_url? assignment['audio_url']})
86
+ assert_all_assets_have_upload_status(csv, ['audio'], 'maybe')
87
+ begin
88
+ tp_assign(dir, good_config_path)
89
+ sandbox_csv = project.local.file('data', 'sandbox-assignment.csv').as(:csv)
90
+ assert_equal(csv.count, sandbox_csv.count)
91
+ assert_equal(sandbox_csv.count, sandbox_csv.select{|assignment| working_url? assignment['audio_url'] }.count)
92
+ assert_all_assets_have_upload_status(csv, ['audio'], 'yes')
93
+ ensure
94
+ tp_finish(dir, good_config_path)
95
+ end #begin
96
+ end # in_temp_tp_dir do...
97
+ end
98
+
99
+ def test_fixing_failed_assignment_html_upload
100
+ skip_if_no_amazon_credentials('tp-assign failed assignment upload integration test')
101
+ skip_if_no_s3_credentials('tp-assign failed assignment upload integration test')
102
+ in_temp_tp_dir do |dir|
103
+ good_config_path = setup_s3_config(dir)
104
+ bad_config_path = setup_s3_config_with_bad_password(dir)
105
+ tp_make(dir, good_config_path, 'mp3')
106
+ begin
107
+ assert(project = temp_tp_dir_project(dir, Typingpool::Config.file(good_config_path)))
108
+ assert(project.local)
109
+ get_assignment_urls = lambda{|csv| csv.map{|assignment| assignment['assignment_url'] }.select{|url| url } }
110
+ assert_empty(get_assignment_urls.call(project.local.file('data', 'assignment.csv').as(:csv)))
111
+ exception = assert_raises(Typingpool::Error::Shell) do
112
+ tp_assign(dir, bad_config_path)
113
+ end #assert_raises...
114
+ assert_match(exception.message, /s3 operation fail/i)
115
+ sandbox_csv = project.local.file('data', 'sandbox-assignment.csv').as(:csv)
116
+ refute_empty(get_assignment_urls.call(sandbox_csv))
117
+ check_assignment_urls = lambda{ get_assignment_urls.call(sandbox_csv).map{|url| Typingpool::Utility.working_url? url } }
118
+ check_assignment_urls.call.each{|checked_out| refute(checked_out) }
119
+ assert_all_assets_have_upload_status(sandbox_csv, ['assignment'], 'maybe')
120
+ tp_assign(dir, good_config_path)
121
+ check_assignment_urls.call.each{|checked_out| assert(checked_out) }
122
+ assert_all_assets_have_upload_status(sandbox_csv, ['assignment'], 'yes')
123
+ ensure
124
+ tp_finish(dir, good_config_path)
125
+ end #begin
126
+ end #in_temp_tp_dir do...
127
+ end
128
+
129
+ def test_abort_on_config_mismatch
130
+ skip_if_no_s3_credentials('tp-assign abort on config mismatch test')
131
+ in_temp_tp_dir do |dir|
132
+ config = config_from_dir(dir)
133
+ good_config_path = setup_s3_config(dir, config, '.config_s3_good')
134
+ tp_make(dir, good_config_path)
135
+ begin
136
+ tp_finish_outside_sandbox(dir, good_config_path)
137
+ assert(config.amazon.bucket)
138
+ new_bucket = 'configmismatch-test'
139
+ refute_equal(new_bucket, config.amazon.bucket)
140
+ config.amazon.bucket = new_bucket
141
+ bad_config_path = setup_s3_config(dir, config, '.config_s3_bad')
142
+ exception = assert_raises(Typingpool::Error::Shell) do
143
+ tp_assign(dir, bad_config_path)
144
+ end #assert_raises...
145
+ assert_match(exception.message, /\burls don't look right\b/i)
146
+ ensure
147
+ tp_finish(dir, good_config_path)
148
+ end #begin
149
+ end #in_temp_tp_dir do...
150
+ end
151
+
152
+ end #TestTpAssign
@@ -0,0 +1,72 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ $:.unshift File.join(File.dirname(File.dirname($0)), 'lib')
4
+
5
+ require 'typingpool'
6
+ require 'typingpool/test'
7
+
8
+ class TestTpReview < Typingpool::Test::Script
9
+
10
+ def test_tp_review
11
+ in_temp_tp_dir do |dir|
12
+ skip_if_no_upload_credentials('tp-review integration test')
13
+ skip_if_no_amazon_credentials('tp-review integration test')
14
+ tp_make(dir)
15
+ copy_fixtures_to_temp_tp_dir(dir, 'tp_review_')
16
+ assert(File.exists? File.join(temp_tp_dir_project_dir(dir), 'data','sandbox-assignment.csv'))
17
+ project = temp_tp_dir_project(dir)
18
+ assert_equal(7, project.local.file('data','sandbox-assignment.csv').as(:csv).reject{|assignment| assignment['hit_id'].to_s.empty? }.count)
19
+ begin
20
+ output = nil
21
+ assert_nothing_raised do
22
+ output = tp_review_with_fixture(dir, File.join(fixtures_dir, 'vcr', 'tp-review-1'), %w(a r a r s q))
23
+ end
24
+ assert_equal(0, output[:status].to_i, "Bad exit code: #{output[:status]} err: #{output[:err]}")
25
+ assert_equal(5, project.local.file('data','sandbox-assignment.csv').as(:csv).reject{|assignment| assignment['hit_id'].to_s.empty? }.count)
26
+ reviews = split_reviews(output[:out])
27
+ assert_match(reviews[1], /Interview\.00\.00/)
28
+ #we can't specify leading \b boundaries because the ansi
29
+ #escape sequences mess that up
30
+ assert_match(reviews[1], /Approved\b/i)
31
+ assert_match(reviews[2], /Interview\.00\.20/)
32
+ assert_match(reviews[2], /reason\b/i)
33
+ assert_match(reviews[2], /Rejected\b/i)
34
+ assert_match(reviews[3], /Interview\.00\.40/)
35
+ assert_match(reviews[3], /Approved\b/i)
36
+ assert_match(reviews[4], /Interview\.01\.00/)
37
+ assert_match(reviews[4], /reason\b/i)
38
+ assert_match(reviews[4], /Rejected\b/i)
39
+ assert_match(reviews[5], /Interview\.01\.20/)
40
+ assert_match(reviews[5], /Skipping\b/i)
41
+ assert_match(reviews[6], /Interview\.02\.00/)
42
+ assert_match(reviews[6], /Quitting\b/i)
43
+ transcript = assert_has_partial_transcript(dir)
44
+ assert_html_has_audio_count(2, transcript)
45
+ assert_assignment_csv_has_transcription_count(2, project, 'sandbox-assignment.csv')
46
+
47
+ assert_nothing_raised do
48
+ output = tp_review_with_fixture(dir, File.join(fixtures_dir, 'vcr', 'tp-review-2'), %w(a r))
49
+ end
50
+ assert_equal(0, output[:status].to_i, "Bad exit code: #{output[:status]} err: #{output[:err]}")
51
+ assert_equal(4, project.local.file('data','sandbox-assignment.csv').as(:csv).reject{|assignment| assignment['hit_id'].to_s.empty? }.count)
52
+ reviews = split_reviews(output[:out])
53
+ assert_match(reviews[1], /Interview\.01\.20/)
54
+ assert_match(reviews[1], /Approved\b/i)
55
+ assert_match(reviews[2], /Interview\.02\.00/)
56
+ assert_match(reviews[2], /reason\b/i)
57
+ assert_match(reviews[2], /Rejected\b/i)
58
+ transcript = assert_has_partial_transcript(dir)
59
+ assert_html_has_audio_count(3, transcript)
60
+ assert_assignment_csv_has_transcription_count(3, project, 'sandbox-assignment.csv')
61
+ ensure
62
+ rm_fixtures_from_temp_tp_dir(dir, 'tp_review_')
63
+ tp_finish(dir)
64
+ end #begin
65
+ end #in_temp_tp_dir
66
+ end
67
+
68
+ def split_reviews(output)
69
+ output.split(/Transcript for\b/)
70
+ end
71
+
72
+ end #class TestTpReview
@@ -0,0 +1,44 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ $:.unshift File.join(File.dirname(File.dirname($0)), 'lib')
4
+
5
+ require 'typingpool'
6
+ require 'typingpool/test'
7
+
8
+ class TestTpCollect < Typingpool::Test::Script
9
+ require 'fileutils'
10
+
11
+ def test_tp_collect
12
+ in_temp_tp_dir do |dir|
13
+ skip_if_no_upload_credentials('tp-collect integration test')
14
+ skip_if_no_amazon_credentials('tp-collect integration test')
15
+ tp_make(dir)
16
+ copy_fixtures_to_temp_tp_dir(dir, 'tp_collect_')
17
+ begin
18
+ project = temp_tp_dir_project(dir)
19
+ assert_nothing_raised do
20
+ tp_collect_with_fixture(dir, File.join(vcr_dir, 'tp-collect-1'))
21
+ end
22
+ transcript = assert_has_partial_transcript(dir)
23
+ assert_html_has_audio_count(2, transcript)
24
+ assert_assignment_csv_has_transcription_count(2, project, 'sandbox-assignment.csv')
25
+ assert_nothing_raised do
26
+ tp_collect_with_fixture(dir, File.join(vcr_dir, 'tp-collect-2'))
27
+ end
28
+ transcript = assert_has_partial_transcript(dir)
29
+ assert_html_has_audio_count(4, transcript)
30
+ assert_assignment_csv_has_transcription_count(4, project, 'sandbox-assignment.csv')
31
+ assert_nothing_raised do
32
+ tp_collect_with_fixture(dir, File.join(vcr_dir, 'tp-collect-3'))
33
+ end
34
+ # transcript = assert_has_transcript(dir) || assert_has_partial_transcript(dir)
35
+ # assert_html_has_audio_count(7, transcript)
36
+ # assert_assignment_csv_has_transcription_count(7, project, 'sandbox-assignment.csv')
37
+ ensure
38
+ rm_fixtures_from_temp_tp_dir(dir, 'tp_collect_')
39
+ tp_finish(dir)
40
+ end #begin
41
+ end #in_temp_tp_dir
42
+ end
43
+
44
+ end #TestTpCollect
@@ -0,0 +1,123 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ $:.unshift File.join(File.dirname(File.dirname($0)), 'lib')
4
+
5
+ require 'typingpool'
6
+ require 'typingpool/test'
7
+
8
+ class TestTpFinish < Typingpool::Test::Script
9
+ def tp_finish_on_audio_files_with(dir, config_path)
10
+ skip_if_no_amazon_credentials('tp-finish audio test')
11
+ skip_if_no_upload_credentials('tp-finish audio test')
12
+ tp_make(dir, config_path)
13
+ project = temp_tp_dir_project(dir, Typingpool::Config.file(config_path))
14
+ csv = project.local.file('data', 'assignment.csv').as(:csv)
15
+ urls = csv.map{|assignment| assignment['audio_url'] }
16
+ refute_empty(urls)
17
+ assert_all_assets_have_upload_status(csv, ['audio'], 'yes')
18
+ assert_equal(urls.size, urls.select{|url| working_url? url}.size)
19
+ assert_nothing_raised do
20
+ tp_finish_outside_sandbox(dir, config_path)
21
+ end
22
+ assert_empty(urls.select{|url| working_url? url })
23
+ assert_all_assets_have_upload_status(csv, ['audio'], 'no')
24
+ end
25
+
26
+ def test_tp_finish_on_audio_files
27
+ in_temp_tp_dir do |dir|
28
+ config_path = self.config_path(dir)
29
+ tp_finish_on_audio_files_with(dir, config_path)
30
+ end
31
+ end
32
+
33
+ def test_tp_finish_on_audio_files_with_s3
34
+ in_temp_tp_dir do |dir|
35
+ config = config_from_dir(dir)
36
+ config.to_hash.delete('sftp')
37
+ config_path = write_config(config, dir)
38
+ tp_finish_on_audio_files_with(dir, config_path)
39
+ end
40
+ end
41
+
42
+ def test_tp_finish_on_amazon_hits
43
+ skip_if_no_amazon_credentials('tp-finish Amazon test')
44
+ skip_if_no_upload_credentials('tp-finish Amazon test')
45
+ in_temp_tp_dir do |dir|
46
+ tp_make(dir)
47
+ tp_assign(dir)
48
+ project = temp_tp_dir_project(dir)
49
+ sandbox_csv = project.local.file('data', 'sandbox-assignment.csv').as(:csv)
50
+ assert_all_assets_have_upload_status(sandbox_csv, ['audio', 'assignment'], 'yes')
51
+ setup_amazon(dir)
52
+ results = Typingpool::Amazon::HIT.all_for_project(project.local.id)
53
+ refute_empty(results)
54
+ assert_nothing_raised do
55
+ tp_finish(dir)
56
+ end
57
+ assert_empty(Typingpool::Amazon::HIT.all_for_project(project.local.id))
58
+ results.each do |result|
59
+ #The original HIT might be gone, or there and marked
60
+ #'disposed', depending whether Amazon has swept the server for
61
+ #dead HITs yet
62
+ begin
63
+ hit = RTurk::Hit.find(result.id)
64
+ assert_match(hit.status, /^dispos/i)
65
+ rescue RTurk::InvalidRequest => exception
66
+ assert_match(exception.message, /HITDoesNotExist/i)
67
+ end #begin
68
+ end #results.each...
69
+ refute(File.exists? sandbox_csv)
70
+ assert_all_assets_have_upload_status(project.local.file('data', 'assignment.csv').as(:csv), ['audio'], 'no')
71
+ end #in_temp_tp_dir
72
+ end
73
+
74
+ def test_tp_finish_with_missing_files
75
+ skip_if_no_amazon_credentials('tp-finish missing files test')
76
+ skip_if_no_upload_credentials('tp-finish missing files test')
77
+ in_temp_tp_dir do |dir|
78
+ project = nil
79
+ tp_make(dir)
80
+ begin
81
+ project = temp_tp_dir_project(dir)
82
+ assignments = project.local.file('data', 'assignment.csv').as(:csv).read
83
+ urls = assignments.map{|assignment| assignment['audio_url'] }
84
+ assert_empty(urls.reject{|url| working_url? url })
85
+ bogus_url = urls.first.sub(/\.mp3/, '.foo.mp3')
86
+ refute_equal(urls.first, bogus_url)
87
+ refute(working_url? bogus_url)
88
+ bogus_assignment = assignments.first.dup
89
+ bogus_assignment['audio_url'] = bogus_url
90
+ assignments.insert(1, bogus_assignment)
91
+ project.local.file('data', 'assignment.csv').as(:csv).write(assignments)
92
+ assert_equal(1, project.local.file('data', 'assignment.csv').as(:csv).reject{|assignment| working_url? assignment['audio_url'] }.count)
93
+ ensure
94
+ tp_finish_outside_sandbox(dir)
95
+ end #begin
96
+ assert_empty(project.local.file('data', 'assignment.csv').as(:csv).select{|assignment| working_url? assignment['audio_url'] })
97
+ end #in_temp_tp_dir...
98
+ end
99
+
100
+ def test_abort_on_config_mismatch
101
+ skip_if_no_s3_credentials('tp-finish abort on config mismatch test')
102
+ in_temp_tp_dir do |dir|
103
+ config = config_from_dir(dir)
104
+ good_config_path = setup_s3_config(dir, config, '.config_s3_good')
105
+ tp_make(dir, good_config_path)
106
+ begin
107
+ assert(config.amazon.bucket)
108
+ new_bucket = 'configmismatch-test'
109
+ refute_equal(new_bucket, config.amazon.bucket)
110
+ config.amazon.bucket = new_bucket
111
+ bad_config_path = setup_s3_config(dir, config, '.config_s3_bad')
112
+ exception = assert_raises(Typingpool::Error::Shell) do
113
+ tp_finish_outside_sandbox(dir, bad_config_path)
114
+ end #assert_raises...
115
+ assert_match(exception.message, /\burls don't look right\b/i)
116
+ ensure
117
+ tp_finish_outside_sandbox(dir, good_config_path)
118
+ end #begin
119
+ end #in_temp_tp_dir do...
120
+
121
+ end
122
+
123
+ end #TestTpFinish