#!/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"

unless defined?(Mypath)
  Mypath  = File.expand_path(File.dirname(__FILE__))
end
old_dir = File.expand_path(Dir.pwd)
if old_dir != Mypath
  Dir.chdir(Mypath)
end

%w(/../ext/cdio /../lib).each do |src_dir|
  $: << Mypath +  src_dir unless $:.member?(src_dir)
end

require "cdio"

class CdioTests < Test::Unit::TestCase

    # 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.
        olddir=Dir.pwd()
        Dir.chdir(Mypath)
        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()
        Dir.chdir(olddir)
    end

    # Test functioning of read routines
    def test_read()
        cuefile=Mypath + "/../data/isofs-m1.cue"
        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= Mypath + "/cdda.cue"
        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=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
Dir.chdir(old_dir)
