#
# Copyright (c) 2012, Ashok P. Nadkarni
# All rights reserved.
#
# See the file LICENSE for license

# This file contains tests for commands from the com.tcl

# TBD - we have no way of checking whether options are set correctly
# since wmi, vbscript etc. cannot deal with the TaskScheduler 1.0 API
# And for some options we cannot run the tests to verify

package require tcltest
eval tcltest::configure $argv

source [file join [file dirname [info script]] testutil.tcl]
load_twapi_package twapi_mstask

namespace eval twapi::mstask::test {
    namespace import ::tcltest::test
    ::tcltest::testConstraint win2k [twapi::min_os_version 5]

    ################################################################

    proc tomorrow {} {
        return [clock format [clock scan tomorrow] -format %Y-%m-%d]
    }

    proc nextyear {} {
        set year [clock format [clock seconds] -format %Y]
        return ${year}-01-01
    }

    proc nextminute {} {
        set now [clock seconds]
        incr now 60
        return [clock format $now -format %H:%M]
    }

    proc onehourlater {} {
        set now [clock seconds]
        incr now 3600
        return [clock format $now -format %H:%M]
    }

    proc setup_standard_mstask {v_taskstrings v_taskints v_taskbools v_triggerstrings v_triggerints v_triggerbools} {
        upvar $v_taskstrings taskstrings
        upvar $v_taskints taskints
        upvar $v_taskbools taskbools
        upvar $v_triggerstrings triggerstrings
        upvar $v_triggerints triggerints
        upvar $v_triggerbools triggerbools

        set taskstrings(-application) [file nativename [info nameofexecutable]]
        set taskstrings(-comment) "This is a TWAPI test task"
        set taskstrings(-creator) "Mr. Test"
        set taskstrings(-data) [binary format c* {1 2 3}]
        set taskbools(-deletewhendone) 1
        set taskbools(-disabled) 1
        set taskbools(-dontstartonbatteries) 1
        set taskbools(-hidden) 0; # Else scheduler control panel does not show
        set taskints(-idlewait) 10
        set taskints(-idlewaitdeadline) 20
        set taskbools(-killifonbatteries) 1
        set taskints(-maxruntime) 100
        set taskstrings(-params) "x y z"
        set taskstrings(-priority) high
        set taskbools(-resumesystem) 1
        set taskbools(-restartonidleresume) true
        set taskbools(-runonlyifloggedon) 1
        set taskbools(-startonlyifidle) 1
        set taskstrings(-workingdir) [tcltest::testsDirectory]

        set triggerstrings(-begindate) [tomorrow]
        set triggerbools(-disabled) 1
        set triggerints(-duration) 15
        set triggerstrings(-enddate) [nextyear]
        set triggerints(-interval) 2
        set triggerbools(-killatdurationend) true
        set triggerints(-period) 5
        set triggerstrings(-starttime) [nextminute]
        set triggerstrings(-type) daily

    }

    proc verify_mstask_values {task_name v_taskstrings v_taskints v_taskbools v_triggerstrings v_triggerints v_triggerbools} {
        set itaskscheduler [twapi::itaskscheduler_new]
        twapi::trap {
            set itask [twapi::itaskscheduler_get_itask $itaskscheduler $task_name]
            twapi::trap {
                array set itaskinfo [twapi::itask_get_info $itask -all]
                set itasktrigger [twapi::itask_get_itasktrigger $itask 0]
                twapi::trap {
                    array set itriggerinfo [twapi::itasktrigger_get_info $itasktrigger]
                } finally {
                    twapi::itasktrigger_release $itasktrigger
                }
            } finally {
                twapi::itask_release $itask
            }
        } finally {
            twapi::itaskscheduler_release $itaskscheduler
        }

        set result {}
        foreach opt [array names taskstrings] {
            if {[string compare -nocase $taskstrings($opt) $itaskinfo($opt)]} {
                lappend result "Mismatch in option $opt: expected $taskstrings($opt), got $itaskinfo($opt)"
            }
        }
        foreach opt [array names taskints] {
            if {$taskints($opt) != $itaskinfo($opt)} {
                lappend result "Mismatch in option $opt: expected $taskints($opt), got $itaskinfo($opt)"
            }
        }
        foreach opt [array names taskbools] {
            if {(! $taskbools($opt)) != (! $itaskinfo($opt))} {
                lappend result "Mismatch in option $opt: expected $taskbools($opt), got $itaskinfo($opt)"
            }
        }

        foreach opt [array names triggerstrings] {
            if {[string compare -nocase $triggerstrings($opt) $itriggerinfo($opt)]} {
                lappend result "Mismatch in option $opt: expected $triggerstrings($opt), got $itriggerinfo($opt)"
            }
        }
        foreach opt [array names triggerints] {
            if {$triggerints($opt) != $itriggerinfo($opt)} {
                lappend result "Mismatch in option $opt: expected $triggerints($opt), got $itriggerinfo($opt)"
            }
        }
        foreach opt [array names triggerbools] {
            if {(! $triggerbools($opt)) != (! $itriggerinfo($opt))} {
                lappend result "Mismatch in option $opt: expected $triggerbools($opt), got $itriggerinfo($opt)"
            }
        }

        return [join $result \n]
    }

    ################################################################


    test mstask_create-1.0 {
        Create a MS Scheduler Task
    } -constraints {
        nt systemmodificationok
    } -body {
        set task_name TWAPITASK_[clock clicks]
        twapi::mstask_create $task_name -application [info nameofexecutable] -begindate [tomorrow]
        file exists [file join $::env(SYSTEMROOT) Tasks ${task_name}.job]
    } -cleanup {
        twapi::mstask_delete $task_name
    } -result 1

    test mstask_create-1.1 {
        Create a MS Scheduler Task and verify its settings using defaults
    } -constraints {
        nt systemmodificationok
    } -body {
        # TBD - account is set to "". Instead create a test account and
        # delete it afterwards
        set task_name TWAPITASK_[clock clicks]

        setup_standard_mstask taskstrings taskints taskbools triggerstrings triggerints triggerbools

        eval [list twapi::mstask_create $task_name -password doesnotmatter] [array get taskbools] [array get taskstrings] [array get taskints] [array get triggerstrings] [array get triggerints] [array get triggerbools]

        verify_mstask_values $task_name taskstrings taskints taskbools triggerstrings triggerints triggerbools
    } -cleanup {
        twapi::mstask_delete $task_name
    } -result ""

    test mstask_create-2.0 {
        Create a MS Scheduler Task and verify that it is actually run as per schedule
    } -constraints {
        nt systemmodificationok
    } -setup {
        puts "This test may take up to a minute to run"
    } -body {
        set task_name TWAPITASK_[clock clicks]
	# We do not use tclTests::makeFile because we don't want file to
	# be left behind if the test fails.
	set path [file join [tcltest::temporaryDirectory] ${task_name}.tmp]
	close [open $path w+]
        set path [file attributes $path -shortname]
        twapi::mstask_create $task_name -account "" -application [info nameofexecutable] -starttime [nextminute] -type once -workingdir [tcltest::testsDirectory] -params "testutil.tcl \"file delete $path\""
        # Wait up to a minute+ for the task to run
        set elapsed 0
        while {[file exists $path] && $elapsed < 70000} {
            after 500
            incr elapsed 500
        }
        file exists $path
    } -cleanup {
        twapi::mstask_delete $task_name
    } -result 0

    test task-100.0 {
        Placeholder multiple triggers, different values for options with
        specific values, -system option
    } -constraints {
	TBD
    } -body {
    } -result ""

    test task-101.0 {
        Check use of encrypted password when creating task (using conceal)
    } -constraints {
	TBD
    } -body {
    } -result ""

    ################################################################

    test mstask_delete-1.0 {
        Create a MS Scheduler Task
    } -constraints {
        nt systemmodificationok
    } -body {
        set task_name TWAPITASK_[clock clicks]
        twapi::mstask_create $task_name -application [info nameofexecutable] -begindate [tomorrow]
        set jobpath [file join $::env(SYSTEMROOT) Tasks ${task_name}.job]
        expr {
              [file exists $jobpath]  &&
              ([twapi::mstask_delete $task_name] eq "") &&
              ![file exists $jobpath]
          }
    } -result 1

    ################################################################

    test itask_run-1.0 {
        Run a task on demand
    } -constraints {
        nt systemmodificationok
    } -setup {
        set task_name TWAPITASK_[clock clicks]
        set path [file attributes [tcltest::makeFile "" ${task_name}.tmp] -shortname]
	# -account "" needed else fails on Win2kr8 (at least, maybe others)
        twapi::mstask_create $task_name -account "" -application [info nameofexecutable] -starttime [onehourlater] -type once -workingdir [tcltest::testsDirectory] -params "testutil.tcl \"file delete $path\""
    } -body {
        set its [twapi::itaskscheduler_new]
        set itask [twapi::itaskscheduler_get_itask $its $task_name]
        twapi::itask_run $itask
	set elapsed 0
        while {[file exists $path] && $elapsed < 5000} {
            after 100
            incr elapsed 100
        }
        file exists $path
    } -cleanup {
        twapi::itask_release $itask
        twapi::itaskscheduler_release $its
        twapi::mstask_delete $task_name
    } -result 0

    ################################################################

    test itaskscheduler_get_tasks-1.0 {
        Enumerate all tasks
    } -constraints {
        nt systemmodificationok
    } -setup {
        set task1 TWAPITASK_[clock clicks]
        set task2 ${task1}_2
        twapi::mstask_create $task1
        twapi::mstask_create $task2
    } -body {
        set its [twapi::itaskscheduler_new]
        set tasks [twapi::itaskscheduler_get_tasks $its]
        expr {
              [lsearch -exact $tasks $task1.job] >= 0 &&
              [lsearch -exact $tasks $task2.job] >= 0
          }
    } -cleanup {
        twapi::itaskscheduler_release $its
        twapi::mstask_delete $task1
        twapi::mstask_delete $task2
    } -result 1

    ################################################################

    test itaskscheduler_get_target_system-1.0 {
        Get the target system for a scheduler
    } -constraints {
        nt systemmodificationok
    } -setup {
        set its [twapi::itaskscheduler_new]
    } -body {
        twapi::itaskscheduler_get_target_system $its
    } -cleanup {
        twapi::itaskscheduler_release $its
    } -result \\\\$::env(COMPUTERNAME)

    ################################################################

    ::tcltest::cleanupTests
}

namespace delete ::twapi::mstask::test
