<project name="grails-functional-test" default="functional-test">
                                                                
    <property environment="env"/>
    <property name="checkoutDir" location="apps"/>
    <property name="app.checkout.url" value="http://svn.codehaus.org/grails/trunk/grails-functional-tests/apps/"/>
    <property name="grails.checkout.url" value="http://svn.codehaus.org/grails/trunk/grails/"/>

    <path id="classpath">
        <fileset dir="lib" includes="*.jar"/>
    </path>

    <taskdef name="svn" classname="org.tigris.subversion.svnant.SvnTask" classpathref="classpath"/>
    <taskdef name="groovy" classname="org.codehaus.groovy.ant.Groovy" classpathref="classpath"/>

    <target name="init" depends="-checkout-grails">
        <!-- will only take effect if we didn't check out -->
        <property name="grails.home" value="${env.GRAILS_HOME}"/>
    </target>

    <macrodef name="grails">
        <attribute name="grailsStarter"
                   default="org.codehaus.groovy.grails.cli.support.GrailsStarter"/>
        <attribute name="grailsScriptRunner"
                   default="org.codehaus.groovy.grails.cli.GrailsScriptRunner"/>
        <attribute name="command" default="help"/>
        <attribute name="projectName" default=""/>
        <sequential>
            <java fork="true" classname="@{grailsStarter}" dir="${checkoutDir}/@{projectName}" resultproperty="testResult">
                <env key="GRAILS_HOME" value="${grails.home}"/>
                <env key="JAVA_OPTS" value="-XX:MaxPermSize=256m -Xmx800m"/>
                <sysproperty key="grails.home" value="${grails.home}"/>
                <sysproperty key="groovy.starter.conf"
                             value="${grails.home}/conf/groovy-starter.conf"/>

                <sysproperty key="disable.auto.recompile" value="false"/>
                <sysproperty key="server.port" value="8080"/>
                <sysproperty key="enable.jndi" value="true"/>
                <sysproperty key="prj.home" value="${checkoutDir}/@{projectName}"/>
                <sysproperty key="base.dir" value="${checkoutDir}/@{projectName}"/>

                <classpath>
                    <path refid="classpath"/>
                    <!-- Mac Only but should do no harm -->
                    <pathelement path="/System/Library/Java"/>
                </classpath>

                <arg line="--main org.codehaus.groovy.grails.cli.GrailsScriptRunner"/>
                <arg line="--conf ${grails.home}/conf/groovy-starter.conf"/>
                <arg line="--classpath ${grails.home}/lib/groovy-all-1.5.2.jar:${grails.home}/dist/grails-cli-1.0-final-SNAPSHOT.jar"/>

                <arg value="@{command}"/>
            </java>
        </sequential>
    </macrodef>

    <target name="-checkout-grails" unless="grails.home.env">
        <property name="grails.home" location="grails"/>
        <delete dir="${grails.home}"/>
        <svn>
            <checkout url="${grails.checkout.url}" destPath="grails"/>
        </svn>
    </target>

    <target name="-build-grails">
        <ant dir="${grails.home}" antfile="build.xml" target="clean" />
        <ant dir="${grails.home}" antfile="build.xml" target="jar">
            <property name="skipTests" value="true"/>
            <property name="skipExamples" value="true"/>
        </ant>
    </target>

    <target name="functional-test"
            description="Runs functional tests for one or more test applications from SVN"
            depends="init">

        <groovy><![CDATA[
            def outcomes = []
            def failure = false

            // Collate the app names
            def listPage = new URL(properties['app.checkout.url']).text
            def appNames = []
            listPage.eachMatch(/>(\w*)\/</) {
                if (it[1] != "..") {
                    appNames << it[1]
                    println "Test will include application ${it[1]}"
                }
            }

            appNames.each() {

                properties.projectName = it

                if (new File("${properties.checkoutDir}/${properties.projectName}").exists()) {
                    ant.antcall(target:"-update-app") {
                        param(name:"projectName", value:properties.projectName)
                    }
                } else {
                    ant.antcall(target:"-checkout-app") {
                        param(name:"projectName", value:properties.projectName)
                    }
                }

                // First upgrade
                ant.grails(command:"upgrade -force", projectName:properties.projectName)
                if (properties.testResult.toInteger() != 0) {
                    outcomes << "Couldn't upgrade application ${properties.projectName}"
                    failure = true
                }

                // Install webtest
                ant.grails(command:"install-plugin webtest", projectName:properties.projectName)
                if (properties.testResult.toInteger() != 0) {
                    outcomes << "Couldn't install webtest plugin into application ${properties.projectName}"
                    failure = true
                }

                // Run webtest
                ant.grails(command:"run-webtest", projectName:"HelloWorld")
                outcomes << "Functional tests in application ${properties.projectName}: " +
                    ((properties.testResult.toInteger() != 0) ? "Failed" : "OK")
                if (properties.testResult.toInteger() != 0) {
                    failure = true
                }
            }

            println "Grails Functional Test Results"
            println "======================================================"
            outcomes.each() {
                println it
            }

            if (failure) ant.fail(message:"At least one of the tests failed")
            ]]>
        </groovy>
    </target>


    <target name="clean">
        <delete dir="${checkoutDir}" failonerror="false"/>
    </target>

    <target name="-checkout-app">
        <echo>Checking out functional test application from :${app.checkout.url}${projectName}</echo>

        <antcall target="-checkout-app-head"/>
    </target>

    <target name="-update-app">
        <echo>Updating local copy of functional test application from :${app.checkout.url}${projectName}</echo>

        <antcall target="-update-app-head"/>
    </target>

    <target name="-checkout-app-head">
        <svn>
            <checkout url="${app.checkout.url}${projectName}" destPath="${checkoutDir}/${projectName}"/>
        </svn>
    </target>

    <target name="-update-app-head">
        <svn>
            <update dir="${checkoutDir}/${projectName}"/>
        </svn>
    </target>
</project>

