#!/usr/bin/env ruby
# $Id: cdiotest.rb,v 1.14 2007/10/13 09:23:17 rocky Exp $

# Unit test for cdio
#
require 'test/unit'
mypath  = File.expand_path(File.dirname(__FILE__))
%w(ext/cdio lib).each do |src_dir|
  $: << File.join(mypath, '..',  src_dir)
end

require 'cdio'

class CdioTests < Test::Unit::TestCase
  
  def setup
    @mypath = File.expand_path(File.dirname(__FILE__))
  end

  # Test running miscellaneous operations
  # No assumption about the CD-ROM drives is made, so
  # we're just going to run operations and see that they
  # don't crash.
  def test_ops()
    device = Cdio::Device.new()
    if Rubycdio::VERSION_NUM >= 76
      # FIXME: Broken on Darwin? 
      # device.open()
      device.ATAPI?()
      # FIXME: Broken on Darwin? 
      # device.media_changed?
    end
    assert_equal(true, true, "Test misc operations")
  end
  
  # Test getting default device
  def test_device_default()
    result1=Cdio::default_device_driver(Rubycdio::DRIVER_DEVICE)
    result2=Cdio::default_device_driver()
    assert_equal(result1, result2,
                 "default_device with/out parameters")
    device = Cdio::Device.new()
    result2=device.device()
    if result1
      assert_equal(result1[0], result2)
      # Now try getting device using driver that we got back
      begin 
        device=Cdio::Device.new(driver_id=result1[1])
        result1 = device.device()
        assert_equal(result1, result2,
                     "default_device using driver name")
      rescue
      end
    end
  end
  
  # Test that various routines raise proper exceptions
  def test_exceptions()
    device = Cdio::Device.new()
    # No CD or or CD image has been set yet. So these fail
    begin 
      lsn = device.disc_last_lsn()
    rescue IOError
      assert_equal(true, true, "last_lsn() IO Error")
    rescue Cdio::DriverError
      assert_equal(true, true, "last_lsn() DriverError")
    else
      assert(false, "last_lsn() should raise error")
    end
    assert_equal("Uninitialized Device", device.disc_mode)
    begin
      track = device.num_tracks()
    rescue IOError
      assert_equal(true, true, "get_num_tracks() IO Error")
    rescue Cdio::DriverError
      assert_equal(true, true, "get_num_tracks() DriverError")
    rescue Cdio::TrackError
      assert_equal(true, true, "get_num_tracks() TrackError")
    else
      assert(false, "last_lsn() should raise error")
    end
    ##        assert_raise(DriverUninitError, device.driver_name)
    ##        assert_raise(DriverUninitError,
    ##                          device.media_changed)
    ##      assert_raise(IOError, device.open, "***Invalid device***")
  end

  # Test that we have image drivers
  def test_have_image_drivers()
    result = Cdio::driver? :"CDRDAO"
    assert_equal(true, result, "Have cdrdrao driver via string")
    result = Cdio::driver? Rubycdio::DRIVER_CDRDAO
    assert_equal(true, result, "Have cdrdrao driver via driver_id")
    result = Cdio::driver? :"NRG"
    assert_equal(true, result, "Have NRG driver via string")
    result = Cdio::driver? Rubycdio::DRIVER_NRG
    assert_equal(true, result, "Have NRG driver via driver_id")
    result = Cdio::driver? :'BIN/CUE'
    assert_equal(true, result, "Have BIN/CUE driver via string")
    result = Cdio::driver? Rubycdio::DRIVER_BINCUE
    assert_equal(true, result, "Have BIN/CUE driver via driver_id")
  end
  
  # Test functioning of cdrdao image routines
  def test_tocfile()
    ## TOC reading needs to be done in the directory where the
    ## TOC/BIN files reside.
    Dir.chdir(File.expand_path(File.dirname(__FILE__))) {
      tocfile="cdda.toc"
      device = Cdio::Device.new(tocfile, Rubycdio::DRIVER_CDRDAO)
      hw  = device.hwinfo()
      assert_equal(true, hw != nil, "get_hwinfo ok")
      assert_equal('libcdio', hw["vendor"], "get_hwinfo vendor")
      assert_equal('cdrdao', hw["model"], "get_hwinfo cdrdao")
      # Test known values of various access parameters:
      # access mode, driver name via string and via driver_id
      # and cue name
      result = device.arg("access-mode")
      assert_equal(result, 'image', 'get_arg("access_mode")')
      result = device.driver_name()
      assert_equal(result, 'CDRDAO', 'get_driver_name')
      result = device.driver_id()
      assert_equal(result, Rubycdio::DRIVER_CDRDAO, 'get_driver_id')
      result = device.arg("source")
      assert_equal(result, tocfile, 'get_arg("source")')
      result = device.media_changed?
      assert_equal(false, result, "tocfile: media_changed?")
      # Test getting is_tocfile
      result = tocfile?(tocfile)
      assert_equal(true, result, "is_tocfile(tocfile)")
      result = nrg? tocfile
      assert_equal(false, result, "is_nrgfile(tocfile)")
      result = device? tocfile
      assert_equal(false, result, "is_device(tocfile)")
      ## FIXME
      ## assert_raise(DriverUnsupportedError,
      ##             (deviceblocksize= 2048))
      ##assert_raise(DriverUnsupportedError,
      ##             (device.speed = 5))
      device.close()
    }
  end
  
  # Test functioning of read routines
  def test_read()
    cuefile = File.join(@mypath, '..', 'data', 'isofs-m1.cue')
    Dir.chdir(@mypath) {
      device  = Cdio::Device.new(cuefile)
      # Read the ISO Primary Volume descriptor
      blocks, data=device.read_sectors(16, Rubycdio::READ_MODE_M1F1)
      assert_equal(data[1..5], 'CD001')
      assert_equal(blocks, 1)
      blocks, data=device.read_data_blocks(26)
      assert_equal(data[6..31], 'GNU GENERAL PUBLIC LICENSE')
    }
  end
  
  # Test functioning of BIN/CUE image routines
  def test_bincue()
    cuefile = File.join(@mypath, 'cdda.cue')
    Dir.chdir(@mypath) {
      device  = Cdio::Device.new(source=cuefile)
      # Test known values of various access parameters:
      # access mode, driver name via string and via driver_id
      # and cue name
      result = device.arg("access-mode")
      assert_equal(result, 'image', 'get_arg("access_mode")')
      result = device.driver_name()
      assert_equal(result, 'BIN/CUE', 'get_driver_name')
      result = device.driver_id()
      assert_equal(result, Rubycdio::DRIVER_BINCUE, 'get_driver_id')
      result = device.arg("cue")
      assert_equal(result, cuefile, 'get_arg("cue")')
      # Test getting binfile? and cuefile?
      binfile = cuefile? cuefile
      assert_equal(true, binfile != nil, "cuefile? cuefile")
      # require "debug"
      cuefile2 = binfile? binfile
      # Could check that cuefile2 == cuefile, but some OS's may 
      # change the case of files
      assert_equal(true, cuefile2 != nil, "cuefile? binfile")
      result = tocfile? cuefile
      assert_equal(false, result, "tocfile? tocfile")
      hw  = device.hwinfo()
      assert_equal(true, hw != nil, "get_hwinfo ok")
      assert_equal('libcdio', hw["vendor"], "get_hwinfo vendor")
      assert_equal('CDRWIN', hw["model"], "get_hwinfo model")
      result = device? cuefile
      assert_equal(false, result, "device? tocfile")
      result = device.media_changed?
      assert_equal(false, result, "binfile: media_changed?")
      if Rubycdio::VERSION_NUM >= 77
        # There's a bug in libcdio 0.76 that causes these to crash
        ### FIXME
        # assert_raise(DriverUnsupportedError,
        #             device.blocksize= 2048)
        # assert_raise(DriverUnsupportedError,
        #             device.speed = 5)
      end
      device.close()
    }
  end
  
  # Test functioning CD-DA
  def test_cdda()
    device  = Cdio::Device.new()
    cuefile = File.join(@mypath, 'cdda.cue')
    device.open(cuefile)
    result = device.disc_mode()
    assert_equal(result, 'CD-DA', 'get_disc_mode')
    assert_equal(device.mcn(), '0000010271955', 'get_mcn')
    ## FIXME
    ## assert_raise(DriverUnsupportedError,
    ##             device.last_session)
    # assert_raise(IOError, device.joliet_level)
    result = device.num_tracks()
    assert_equal(result, 1, 'get_num_tracks')
    disc_last_lsn = device.disc_last_lsn()
    assert_equal(disc_last_lsn, 302, 'get_disc_last_lsn')
    t=device.last_track()
    assert_equal(t.track, 1, 'last_track')
    assert_equal(t.last_lsn(), 301, '(track) last_lsn')
    assert_equal(device.track_for_lsn(t.last_lsn()).track,
                 t.track)
    t=device.first_track()
    assert_equal(t.track, 1, 'get_first_track')
    assert_equal(t.format(), 'audio', 'get_track_format')
    assert_equal(t.msf(), "00:02:00", "get_msf")
    device.close()
  end
end
