#!/usr/bin/env ruby
require './mp3tag'
require 'runit/testcase'

class Mp3TagTest < RUNIT::TestCase

  Mp3File = '/tmp/1.mp3'

  def setup
    system("cp '#{ARGV[0]}' #{Mp3File}")
  end

  def test_hastag
    Mp3Tag.new(Mp3File).commit
    assert(Mp3Tag.hastag?(Mp3File) == true)
    Mp3Tag.removetag(Mp3File)
    assert(Mp3Tag.hastag?(Mp3File) == false)
  end

  def test_addtag
    Mp3Tag.removetag(Mp3File)
    size_without_tag = File.stat(Mp3File).size
    Mp3Tag.new(Mp3File).commit
    size_with_tag = File.stat(Mp3File).size
    assert(size_with_tag - size_without_tag == 128)
  end

  def test_removetag
    Mp3Tag.new(Mp3File).commit
    size_with_tag = File.stat(Mp3File).size
    Mp3Tag.removetag(Mp3File)
    size_without_tag = File.stat(Mp3File).size
    assert(size_with_tag - size_without_tag == 128)
  end

  def test_integrity
    Mp3Tag.removetag(Mp3File)
    md5_before = `md5sum #{Mp3File}`
    Mp3Tag.new(Mp3File).commit
    Mp3Tag.removetag(Mp3File)
    md5_after = `md5sum #{Mp3File}`
    assert(md5_after == md5_before)

    Mp3Tag.new(Mp3File).commit
    md5_before = `md5sum #{Mp3File}`
    Mp3Tag.removetag(Mp3File)
    Mp3Tag.new(Mp3File).commit
    md5_after = `md5sum #{Mp3File}`
    assert(md5_after == md5_before)
  end

  def check_change
    tag = Mp3Tag.new(Mp3File)
    yield(tag)
    tag.commit

    tagnow = Mp3Tag.new(Mp3File)

    assert_equal tag.songname, tagnow.songname
    assert_equal tag.artist, tagnow.artist
    assert_equal tag.album, tagnow.album
    assert_equal tag.artist, tagnow.artist
    assert_equal tag.album, tagnow.album
    assert_equal tag.year, tagnow.year
    assert_equal tag.genre_id, tagnow.genre_id
    assert_equal tag.comment, tagnow.comment
    assert_equal tag.tracknum, tagnow.tracknum
  end

  def test_edit
    Mp3Tag.removetag(Mp3File)

    [ 'songname', 'artist', 'album', 'comment' ].each { |attr|
      check_change { |tag|
	tag.send("#{attr}=", "Test #{attr}")
      }
    }

    check_change { |tag|
      tag.year = 1923
    }

    check_change { |tag|
      tag.year = "1923"
    }

    check_change { |tag|
      tag.genre_id = 128
    }

    check_change { |tag|
      tag.genre_id = "128"
    }

    check_change { |tag|
      tag.tracknum = 23
    }

    check_change { |tag|
      tag.tracknum = "23"
    }

    check_change { |tag|
      tag.genre_id = 38
    }

    check_change { |tag|
      tag.genre_id = "38"
    }
  end

  def test_genres
    tag = Mp3Tag.new(Mp3File)
    tag.genre_id = 38
    assert_equal(tag.genre, "Gospel")
    tag.genre = "Noise"
    assert_equal(tag.genre_id, 39)
  end

  def test_overfull
    longstring = "ANameWhichIsLongerThan30Characters"

    tag = Mp3Tag.new(Mp3File)
    tag.songname = longstring
    tag.artist = "Artist"
    tag.comment = longstring
    tag.tracknum = 88
    tag.commit

    ntag = Mp3Tag.new(Mp3File)
    assert_equal(longstring[0,30], ntag.songname)
    assert_equal(tag.artist, ntag.artist)
    assert_equal(longstring[0,28], ntag.comment)
    assert_equal(tag.tracknum, ntag.tracknum)
  end

  def test_newtag
    Mp3Tag.removetag(Mp3File)
    tag = Mp3Tag.new(Mp3File)
    assert_equal(255, tag.genre_id)
    assert_equal(0, tag.year)
    assert_equal(0, tag.tracknum)
    assert_equal('', tag.songname)
    assert_equal('', tag.artist)
    assert_equal('', tag.album)
    assert_equal('', tag.comment)
  end

  def test_misc
    tag = Mp3Tag.new(Mp3File)
    tag.genre = "NoSuchGenre"
    assert_equal(255, tag.genre_id)
    assert_equal("Unknown", tag.genre)
  end

end

if $0 == __FILE__ 
  if (ARGV[0].nil?) || (!FileTest.file? ARGV[0])
    $stderr.puts "Must supply a name of an existing mp3 filename as argument.
The file will be copied before modified - your original will never be changed."
    exit 1
  end
  require 'runit/cui/testrunner'
  RUNIT::CUI::TestRunner.run(Mp3TagTest.suite)
end

