1 require File.dirname(__FILE__) + '/abstract_unit'
 
   3 require File.dirname(__FILE__) + '/fixtures/entry'
 
   5 class Movie < ActiveRecord::Base
 
   9 class FileColumnTest < Test::Unit::TestCase
 
  12     # we define the file_columns here so that we can change
 
  13     # settings easily in a single test
 
  15     Entry.file_column :image
 
  16     Entry.file_column :file
 
  17     Movie.file_column :movie
 
  23     FileUtils.rm_rf File.dirname(__FILE__)+"/public/entry/"
 
  24     FileUtils.rm_rf File.dirname(__FILE__)+"/public/movie/"
 
  25     FileUtils.rm_rf File.dirname(__FILE__)+"/public/my_store_dir/"
 
  28   def test_column_write_method
 
  29     assert Entry.new.respond_to?("image=")
 
  32   def test_column_read_method
 
  33     assert Entry.new.respond_to?("image")
 
  36   def test_sanitize_filename
 
  37     assert_equal "test.jpg", FileColumn::sanitize_filename("test.jpg")
 
  38     assert FileColumn::sanitize_filename("../../very_tricky/foo.bar") !~ /[\\\/]/, "slashes not removed"
 
  39     assert_equal "__foo", FileColumn::sanitize_filename('`*foo')
 
  40     assert_equal "foo.txt", FileColumn::sanitize_filename('c:\temp\foo.txt')
 
  41     assert_equal "_.", FileColumn::sanitize_filename(".")
 
  44   def test_default_options
 
  46     assert_match %r{/public/entry/image}, e.image_options[:store_dir]
 
  47     assert_match %r{/public/entry/image/tmp}, e.image_options[:tmp_base_dir]
 
  50   def test_assign_without_save_with_tempfile
 
  51     do_test_assign_without_save(:tempfile)
 
  54   def test_assign_without_save_with_stringio
 
  55     do_test_assign_without_save(:stringio)
 
  58   def do_test_assign_without_save(upload_type)
 
  60     e.image = uploaded_file(file_path("skanthak.png"), "image/png", "skanthak.png", upload_type)
 
  61     assert e.image.is_a?(String), "#{e.image.inspect} is not a String"
 
  62     assert File.exists?(e.image)
 
  63     assert FileUtils.identical?(e.image, file_path("skanthak.png"))
 
  66   def test_filename_preserved
 
  68     e.image = uploaded_file(file_path("kerb.jpg"), "image/jpeg", "local_filename.jpg")
 
  69     assert_equal "local_filename.jpg", File.basename(e.image)
 
  72   def test_filename_stored_in_attribute
 
  73     e = Entry.new("image" => uploaded_file(file_path("kerb.jpg"), "image/jpeg", "kerb.jpg"))
 
  74     assert_equal "kerb.jpg", e["image"]
 
  77   def test_extension_added
 
  79     e.image = uploaded_file(file_path("kerb.jpg"), "image/jpeg", "local_filename")
 
  80     assert_equal "local_filename.jpg", File.basename(e.image)
 
  81     assert_equal "local_filename.jpg", e["image"]
 
  84   def test_no_extension_without_content_type
 
  86     e.image = uploaded_file(file_path("kerb.jpg"), "something/unknown", "local_filename")
 
  87     assert_equal "local_filename", File.basename(e.image)
 
  88     assert_equal "local_filename", e["image"]
 
  91   def test_extension_unknown_type
 
  93     e.image = uploaded_file(file_path("kerb.jpg"), "not/known", "local_filename")
 
  94     assert_equal "local_filename", File.basename(e.image)
 
  95     assert_equal "local_filename", e["image"]
 
  98   def test_extension_unknown_type_with_extension
 
 100     e.image = uploaded_file(file_path("kerb.jpg"), "not/known", "local_filename.abc")
 
 101     assert_equal "local_filename.abc", File.basename(e.image)
 
 102     assert_equal "local_filename.abc", e["image"]
 
 105   def test_extension_corrected
 
 107     e.image = uploaded_file(file_path("kerb.jpg"), "image/jpeg", "local_filename.jpeg")
 
 108     assert_equal "local_filename.jpg", File.basename(e.image)
 
 109     assert_equal "local_filename.jpg", e["image"]
 
 112   def test_double_extension
 
 114     e.image = uploaded_file(file_path("kerb.jpg"), "application/x-tgz", "local_filename.tar.gz")
 
 115     assert_equal "local_filename.tar.gz", File.basename(e.image)
 
 116     assert_equal "local_filename.tar.gz", e["image"]
 
 119   FILE_UTILITY = "/usr/bin/file"
 
 121   def test_get_content_type_with_file
 
 122     Entry.file_column :image, :file_exec => FILE_UTILITY
 
 124     # run this test only if the machine we are running on
 
 125     # has the file utility installed
 
 126     if File.executable?(FILE_UTILITY)
 
 128       file = FileColumn::TempUploadedFile.new(e, "image")
 
 129       file.instance_variable_set :@dir, File.dirname(file_path("kerb.jpg"))
 
 130       file.instance_variable_set :@filename, File.basename(file_path("kerb.jpg"))
 
 132       assert_equal "image/jpeg", file.get_content_type
 
 134       puts "Warning: Skipping test_get_content_type_with_file test as '#{options[:file_exec]}' does not exist"
 
 138   def test_fix_extension_with_file
 
 139     Entry.file_column :image, :file_exec => FILE_UTILITY
 
 141     # run this test only if the machine we are running on
 
 142     # has the file utility installed
 
 143     if File.executable?(FILE_UTILITY)
 
 144       e = Entry.new(:image => uploaded_file(file_path("skanthak.png"), "", "skanthak.jpg"))
 
 146       assert_equal "skanthak.png", File.basename(e.image)
 
 148       puts "Warning: Skipping test_fix_extension_with_file test as '#{options[:file_exec]}' does not exist"
 
 152   def test_do_not_fix_file_extensions
 
 153     Entry.file_column :image, :fix_file_extensions => false
 
 155     e = Entry.new(:image => uploaded_file(file_path("kerb.jpg"), "image/jpeg", "kerb"))
 
 157     assert_equal "kerb", File.basename(e.image)
 
 160   def test_correct_extension
 
 162     file = FileColumn::TempUploadedFile.new(e, "image")
 
 164     assert_equal "filename.jpg", file.correct_extension("filename.jpeg","jpg")
 
 165     assert_equal "filename.tar.gz", file.correct_extension("filename.jpg","tar.gz")
 
 166     assert_equal "filename.jpg", file.correct_extension("filename.tar.gz","jpg")
 
 167     assert_equal "Protokoll_01.09.2005.doc", file.correct_extension("Protokoll_01.09.2005","doc")
 
 168     assert_equal "strange.filenames.exist.jpg", file.correct_extension("strange.filenames.exist","jpg")
 
 169     assert_equal "another.strange.one.jpg", file.correct_extension("another.strange.one.png","jpg")
 
 172   def test_assign_with_save
 
 174     e.image = uploaded_file(file_path("kerb.jpg"), "image/jpeg", "kerb.jpg")
 
 175     tmp_file_path = e.image
 
 177     assert File.exists?(e.image)
 
 178     assert FileUtils.identical?(e.image, file_path("kerb.jpg"))
 
 179     assert_equal "#{e.id}/kerb.jpg", e.image_relative_path
 
 180     assert !File.exists?(tmp_file_path), "temporary file '#{tmp_file_path}' not removed"
 
 181     assert !File.exists?(File.dirname(tmp_file_path)), "temporary directory '#{File.dirname(tmp_file_path)}' not removed"
 
 185     assert_equal local_path, e.image
 
 190     e.image = uploaded_file(file_path("kerb.jpg"), "image/jpeg", "kerb.jpg")
 
 193     assert_equal_paths File.join(RAILS_ROOT, "public", "entry", "image", e.id.to_s), e.image_dir
 
 194     assert_equal File.join(e.id.to_s), e.image_relative_dir
 
 197   def test_store_dir_callback
 
 198     Entry.file_column :image, {:store_dir => :my_store_dir}
 
 201     e.image = uploaded_file(file_path("kerb.jpg"), "image/jpeg", "kerb.jpg")    
 
 204     assert_equal_paths File.join(RAILS_ROOT, "public", "my_store_dir", e.id), e.image_dir   
 
 207   def test_tmp_dir_with_store_dir_callback
 
 208     Entry.file_column :image, {:store_dir => :my_store_dir}
 
 210     e.image = upload(f("kerb.jpg"))
 
 212     assert_equal File.expand_path(File.join(RAILS_ROOT, "public", "my_store_dir", "tmp")), File.expand_path(File.join(e.image_dir,".."))
 
 215   def test_invalid_store_dir_callback
 
 216     Entry.file_column :image, {:store_dir => :my_store_dir_doesnt_exit}    
 
 218     assert_raise(ArgumentError) {
 
 219       e.image = uploaded_file(file_path("kerb.jpg"), "image/jpeg", "kerb.jpg")
 
 224   def test_subdir_parameter
 
 226     assert_nil e.image("thumb")
 
 227     assert_nil e.image_relative_path("thumb")
 
 228     assert_nil e.image(nil)
 
 230     e.image = uploaded_file(file_path("kerb.jpg"), "image/jpeg", "kerb.jpg")
 
 232     assert_equal "kerb.jpg", File.basename(e.image("thumb"))
 
 233     assert_equal "kerb.jpg", File.basename(e.image_relative_path("thumb"))
 
 235     assert_equal File.join(e.image_dir,"thumb","kerb.jpg"), e.image("thumb")
 
 236     assert_match %r{/thumb/kerb\.jpg$}, e.image_relative_path("thumb") 
 
 238     assert_equal e.image, e.image(nil)
 
 239     assert_equal e.image_relative_path, e.image_relative_path(nil)
 
 242   def test_cleanup_after_destroy
 
 243     e = Entry.new("image" => uploaded_file(file_path("kerb.jpg"), "image/jpeg", "kerb.jpg"))
 
 246     assert File.exists?(local_path)
 
 248     assert !File.exists?(local_path), "'#{local_path}' still exists although entry was destroyed"
 
 249     assert !File.exists?(File.dirname(local_path))
 
 252   def test_keep_tmp_image
 
 253     e = Entry.new("image" => uploaded_file(file_path("kerb.jpg"), "image/jpeg", "kerb.jpg"))
 
 254     e.validation_should_fail = true
 
 255     assert !e.save, "e should not save due to validation errors"
 
 256     assert File.exists?(local_path = e.image)
 
 257     image_temp = e.image_temp
 
 258     e = Entry.new("image_temp" => image_temp)
 
 259     assert_equal local_path, e.image
 
 261     assert FileUtils.identical?(e.image, file_path("kerb.jpg"))
 
 264   def test_keep_tmp_image_with_existing_image
 
 265     e = Entry.new("image" =>uploaded_file(file_path("kerb.jpg"), "image/jpeg", "kerb.jpg"))
 
 267     assert File.exists?(local_path = e.image)
 
 269     e.image = uploaded_file(file_path("skanthak.png"), "image/png", "skanthak.png")
 
 270     e.validation_should_fail = true
 
 272     temp_path = e.image_temp
 
 274     e.image_temp = temp_path
 
 277     assert FileUtils.identical?(e.image, file_path("skanthak.png"))
 
 278     assert !File.exists?(local_path), "old image has not been deleted"
 
 281   def test_replace_tmp_image_temp_first
 
 282     do_test_replace_tmp_image([:image_temp, :image])
 
 285   def test_replace_tmp_image_temp_last
 
 286     do_test_replace_tmp_image([:image, :image_temp])
 
 289   def do_test_replace_tmp_image(order)
 
 290     e = Entry.new("image" => uploaded_file(file_path("kerb.jpg"), "image/jpeg", "kerb.jpg"))
 
 291     e.validation_should_fail = true
 
 293     image_temp = e.image_temp
 
 295     new_img = uploaded_file(file_path("skanthak.png"), "image/png", "skanthak.png")
 
 299       when :image_temp then e.image_temp = image_temp
 
 300       when :image then e.image = new_img
 
 304     assert FileUtils.identical?(e.image, file_path("skanthak.png")), "'#{e.image}' is not the expected 'skanthak.png'"
 
 305     assert !File.exists?(temp_path), "temporary file '#{temp_path}' is not cleaned up"
 
 306     assert !File.exists?(File.dirname(temp_path)), "temporary directory not cleaned up"
 
 307     assert e.image_just_uploaded?
 
 310   def test_replace_image_on_saved_object
 
 311     e = Entry.new("image" => uploaded_file(file_path("kerb.jpg"), "image/jpeg", "kerb.jpg"))
 
 315     e.image = uploaded_file(file_path("skanthak.png"), "image/png", "skanthak.png")
 
 317     assert FileUtils.identical?(file_path("skanthak.png"), e.image)
 
 318     assert old_file != e.image
 
 319     assert !File.exists?(old_file), "'#{old_file}' has not been cleaned up"
 
 322   def test_edit_without_touching_image
 
 323     e = Entry.new("image" => uploaded_file(file_path("kerb.jpg"), "image/jpeg", "kerb.jpg"))
 
 327     assert FileUtils.identical?(file_path("kerb.jpg"), e.image)
 
 330   def test_save_without_image
 
 337   def test_delete_saved_image
 
 338     e = Entry.new("image" => uploaded_file(file_path("kerb.jpg"), "image/jpeg", "kerb.jpg"))
 
 343     assert File.exists?(local_path), "file '#{local_path}' should not be deleted until transaction is saved"
 
 346     assert !File.exists?(local_path)
 
 348     assert e["image"].blank?
 
 353   def test_delete_tmp_image
 
 354     e = Entry.new("image" => uploaded_file(file_path("kerb.jpg"), "image/jpeg", "kerb.jpg"))
 
 358     assert e["image"].blank?
 
 359     assert !File.exists?(local_path)
 
 362   def test_delete_nonexistant_image
 
 369   def test_delete_image_on_non_null_column
 
 370     e = Entry.new("file" => upload(f("skanthak.png")))
 
 374     assert File.exists?(local_path)
 
 377     assert !File.exists?(local_path)
 
 381     e = Entry.new("image" => uploaded_file(file_path("kerb.jpg"), "image/jpeg", 'c:\images\kerb.jpg'))
 
 382     assert e.image_relative_path =~ /^tmp\/[\d\.]+\/kerb\.jpg$/, "relative path '#{e.image_relative_path}' was not as expected"
 
 383     assert File.exists?(e.image)
 
 386   def test_just_uploaded?
 
 387     e = Entry.new("image" => uploaded_file(file_path("kerb.jpg"), "image/jpeg", 'c:\images\kerb.jpg'))
 
 388     assert e.image_just_uploaded?
 
 390     assert e.image_just_uploaded?
 
 392     e = Entry.new("image" => uploaded_file(file_path("kerb.jpg"), "image/jpeg", 'kerb.jpg'))
 
 393     temp_path = e.image_temp
 
 394     e = Entry.new("image_temp" => temp_path)
 
 395     assert !e.image_just_uploaded?
 
 397     assert !e.image_just_uploaded?
 
 406   def test_empty_tmp_with_image
 
 409     e.image = uploaded_file(file_path("kerb.jpg"), "image/jpeg", 'c:\images\kerb.jpg')
 
 411     assert File.exists?(local_path)
 
 413     assert local_path, e.image
 
 416   def test_empty_filename
 
 418     assert_equal "", e["file"]
 
 420     assert_nil e["image"]
 
 424   def test_with_two_file_columns
 
 426     e.image = uploaded_file(file_path("kerb.jpg"), "image/jpeg", "kerb.jpg")
 
 427     e.file = uploaded_file(file_path("skanthak.png"), "image/png", "skanthak.png")
 
 429     assert_match %{/entry/image/}, e.image
 
 430     assert_match %{/entry/file/}, e.file
 
 431     assert FileUtils.identical?(e.image, file_path("kerb.jpg"))
 
 432     assert FileUtils.identical?(e.file, file_path("skanthak.png"))
 
 435   def test_with_two_models
 
 436     e = Entry.new(:image => uploaded_file(file_path("kerb.jpg"), "image/jpeg", "kerb.jpg"))
 
 437     m = Movie.new(:movie => uploaded_file(file_path("skanthak.png"), "image/png", "skanthak.png"))
 
 440     assert_match %{/entry/image/}, e.image
 
 441     assert_match %{/movie/movie/}, m.movie
 
 442     assert FileUtils.identical?(e.image, file_path("kerb.jpg"))
 
 443     assert FileUtils.identical?(m.movie, file_path("skanthak.png"))
 
 446   def test_no_file_uploaded
 
 448     assert_nothing_raised { e.image =
 
 449         uploaded_file(nil, "application/octet-stream", "", :stringio) }
 
 450     assert_equal nil, e.image
 
 453   # when safari submits a form where no file has been
 
 454   # selected, it does not transmit a content-type and
 
 455   # the result is an empty string ""
 
 456   def test_no_file_uploaded_with_safari
 
 458     assert_nothing_raised { e.image = "" }
 
 459     assert_equal nil, e.image
 
 462   def test_detect_wrong_encoding
 
 464     assert_raise(TypeError) { e.image ="img42.jpg" }
 
 467   def test_serializable_before_save
 
 469     e.image = uploaded_file(file_path("skanthak.png"), "image/png", "skanthak.png")
 
 470     assert_nothing_raised { 
 
 471       flash = Marshal.dump(e) 
 
 472       e = Marshal.load(flash)
 
 474     assert File.exists?(e.image)
 
 477   def test_should_call_after_upload_on_new_upload
 
 478     Entry.file_column :image, :after_upload => [:after_assign]
 
 480     e.image = upload(f("skanthak.png"))
 
 481     assert e.after_assign_called?
 
 484   def test_should_call_user_after_save_on_save
 
 485     e = Entry.new(:image => upload(f("skanthak.png")))
 
 488     assert_kind_of FileColumn::PermanentUploadedFile, e.send(:image_state)
 
 489     assert e.after_save_called?
 
 493   def test_assign_standard_files
 
 495     e.image = File.new(file_path('skanthak.png'))
 
 497     assert_equal 'skanthak.png', File.basename(e.image)
 
 498     assert FileUtils.identical?(file_path('skanthak.png'), e.image)
 
 504   def test_validates_filesize
 
 505     Entry.validates_filesize_of :image, :in => 50.kilobytes..100.kilobytes
 
 507     e = Entry.new(:image => upload(f("kerb.jpg")))
 
 510     e.image = upload(f("skanthak.png"))
 
 512     assert e.errors.invalid?("image")
 
 515   def test_validates_file_format_simple
 
 516     e = Entry.new(:image => upload(f("skanthak.png")))
 
 519     Entry.validates_file_format_of :image, :in => ["jpg"]
 
 521     e.image = upload(f("kerb.jpg"))
 
 524     e.image = upload(f("mysql.sql"))
 
 526     assert e.errors.invalid?("image")
 
 530   def test_validates_image_size
 
 531     Entry.validates_image_size :image, :min => "640x480"
 
 533     e = Entry.new(:image => upload(f("kerb.jpg")))
 
 536     e = Entry.new(:image => upload(f("skanthak.png")))
 
 538     assert e.errors.invalid?("image")
 
 541   def do_permission_test(uploaded_file, permissions=0641)
 
 542     Entry.file_column :image, :permissions => permissions
 
 544     e = Entry.new(:image => uploaded_file)
 
 547     assert_equal permissions, (File.stat(e.image).mode & 0777)
 
 550   def test_permissions_with_small_file
 
 551     do_permission_test upload(f("skanthak.png"), :guess, :stringio)
 
 554   def test_permission_with_big_file
 
 555     do_permission_test upload(f("kerb.jpg"))
 
 558   def test_permission_that_overrides_umask
 
 559     do_permission_test upload(f("skanthak.png"), :guess, :stringio), 0666
 
 560     do_permission_test upload(f("kerb.jpg")), 0666
 
 563   def test_access_with_empty_id
 
 564     # an empty id might happen after a clone or through some other
 
 565     # strange event. Since we would create a path that contains nothing
 
 566     # where the id would have been, we should fail fast with an exception
 
 569     e = Entry.new(:image => upload(f("skanthak.png")))
 
 576     assert_raise(RuntimeError) { e.image }
 
 580     assert_raise(RuntimeError) { e.image }
 
 584 # Tests for moving temp dir to permanent dir
 
 585 class FileColumnMoveTest < Test::Unit::TestCase
 
 588     # we define the file_columns here so that we can change
 
 589     # settings easily in a single test
 
 591     Entry.file_column :image
 
 596     FileUtils.rm_rf File.dirname(__FILE__)+"/public/entry/"
 
 599   def test_should_move_additional_files_from_tmp
 
 601     e.image = uploaded_file(file_path("skanthak.png"), "image/png", "skanthak.png")
 
 602     FileUtils.cp file_path("kerb.jpg"), File.dirname(e.image)
 
 604     dir = File.dirname(e.image)
 
 605     assert File.exists?(File.join(dir, "skanthak.png"))
 
 606     assert File.exists?(File.join(dir, "kerb.jpg"))
 
 609   def test_should_move_direcotries_on_save
 
 610     e = Entry.new(:image => upload(f("skanthak.png")))
 
 612     FileUtils.mkdir( e.image_dir+"/foo" )
 
 613     FileUtils.cp file_path("kerb.jpg"), e.image_dir+"/foo/kerb.jpg"
 
 617     assert File.exists?(e.image)
 
 618     assert File.exists?(File.dirname(e.image)+"/foo/kerb.jpg")
 
 621   def test_should_overwrite_dirs_with_files_on_reupload
 
 622     e = Entry.new(:image => upload(f("skanthak.png")))
 
 624     FileUtils.mkdir( e.image_dir+"/kerb.jpg")
 
 625     FileUtils.cp file_path("kerb.jpg"), e.image_dir+"/kerb.jpg/"
 
 628     e.image = upload(f("kerb.jpg"))
 
 631     assert File.file?(e.image_dir+"/kerb.jpg")
 
 634   def test_should_overwrite_files_with_dirs_on_reupload
 
 635     e = Entry.new(:image => upload(f("skanthak.png")))
 
 638     assert File.file?(e.image_dir+"/skanthak.png")
 
 640     e.image = upload(f("kerb.jpg"))
 
 641     FileUtils.mkdir(e.image_dir+"/skanthak.png")
 
 644     assert File.file?(e.image_dir+"/kerb.jpg")
 
 645     assert !File.file?(e.image_dir+"/skanthak.png")
 
 646     assert File.directory?(e.image_dir+"/skanthak.png")