testsuite-script.c   [plain text]


/* Copyright (c) 2002-2011 Pigeonhole authors, see the included COPYING file
 */

#include "lib.h"

#include "sieve.h"
#include "sieve-common.h"
#include "sieve-script.h"
#include "sieve-binary.h"
#include "sieve-interpreter.h"
#include "sieve-runtime-trace.h"
#include "sieve-result.h"

#include "testsuite-common.h"
#include "testsuite-settings.h"
#include "testsuite-log.h"
#include "testsuite-result.h"

#include "testsuite-script.h"

/*
 * Tested script environment
 */ 

struct sieve_binary *_testsuite_compiled_script;

void testsuite_script_init(void)
{
	_testsuite_compiled_script = NULL;
}

void testsuite_script_deinit(void)
{
	if ( _testsuite_compiled_script != NULL ) {
		sieve_binary_unref(&_testsuite_compiled_script);
	}
}

static struct sieve_binary *_testsuite_script_compile
(const struct sieve_runtime_env *renv, const char *script)
{
	struct sieve_instance *svinst = testsuite_sieve_instance;
	struct sieve_binary *sbin;
	const char *sieve_dir;
	const char *script_path;

	sieve_runtime_trace(renv, SIEVE_TRLVL_TESTS, "compile script `%s'", script);

	script_path = sieve_script_dirpath(renv->script);
	if ( script_path == NULL ) 
		return SIEVE_EXEC_FAILURE;

	script_path = t_strconcat(script_path, "/", script, NULL);

	/* Initialize environment */
	sieve_dir = strrchr(script_path, '/');
	if ( sieve_dir == NULL )
		sieve_dir= "./";
	else
		sieve_dir = t_strdup_until(script_path, sieve_dir+1);

	/* Currently needed for include (FIXME) */
	testsuite_setting_set
		("sieve_dir", t_strconcat(sieve_dir, "included", NULL));
	testsuite_setting_set
		("sieve_global_dir", t_strconcat(sieve_dir, "included-global", NULL));
	
	if ( (sbin = sieve_compile(svinst, script_path, NULL, testsuite_log_ehandler,
		NULL)) == NULL )
		return NULL;

	return sbin;
}

bool testsuite_script_compile
(const struct sieve_runtime_env *renv, const char *script)
{
	struct sieve_binary *sbin;

	testsuite_log_clear_messages();

	if ( (sbin=_testsuite_script_compile(renv, script)) == NULL )
		return FALSE;

	if ( _testsuite_compiled_script != NULL ) {
		sieve_binary_unref(&_testsuite_compiled_script);
	}

	_testsuite_compiled_script = sbin;

	return TRUE;
}

bool testsuite_script_run(const struct sieve_runtime_env *renv)
{
	struct sieve_script_env scriptenv;
	struct sieve_result *result;
	struct sieve_interpreter *interp;
	int ret;

	if ( _testsuite_compiled_script == NULL ) {
		sieve_runtime_error(renv, NULL,
			"testsuite: trying to run script, but no script compiled yet");
		return FALSE;
	}

	testsuite_log_clear_messages();

	/* Compose script execution environment */
	memset(&scriptenv, 0, sizeof(scriptenv));
	scriptenv.default_mailbox = "INBOX";
	scriptenv.username = "user";
	scriptenv.hostname = "host.example.com";
	scriptenv.postmaster_address = "postmaster@example.com";
	scriptenv.smtp_open = NULL;
	scriptenv.smtp_close = NULL;
	scriptenv.duplicate_mark = NULL;
	scriptenv.duplicate_check = NULL;
	scriptenv.user = renv->scriptenv->user;
	scriptenv.trace_stream = renv->scriptenv->trace_stream;
	scriptenv.trace_config = renv->scriptenv->trace_config;
	
	result = testsuite_result_get();

	/* Execute the script */
	interp=sieve_interpreter_create(_testsuite_compiled_script, renv->msgdata, 
		&scriptenv, testsuite_log_ehandler);
	
	if ( interp == NULL )
		return SIEVE_EXEC_BIN_CORRUPT;
		
	ret = sieve_interpreter_run(interp, result);

	sieve_interpreter_free(&interp);

	return ( ret > 0 );
}

struct sieve_binary *testsuite_script_get_binary(void)
{
	return _testsuite_compiled_script;
}

void testsuite_script_set_binary(struct sieve_binary *sbin)
{
	if ( _testsuite_compiled_script != NULL ) {
		sieve_binary_unref(&_testsuite_compiled_script);
	}

	_testsuite_compiled_script = sbin;
	sieve_binary_ref(sbin);
}

/*
 * Multiscript
 */

bool testsuite_script_multiscript
(const struct sieve_runtime_env *renv, ARRAY_TYPE (const_string) *scriptfiles)
{
	struct sieve_instance *svinst = testsuite_sieve_instance;
	struct sieve_script_env scriptenv;
	struct sieve_multiscript *mscript;
	const char *const *scripts;
	unsigned int count, i;
	bool more = TRUE;
	bool result = TRUE;

	testsuite_log_clear_messages();

	/* Compose script execution environment */
	memset(&scriptenv, 0, sizeof(scriptenv));
	scriptenv.default_mailbox = "INBOX";
	scriptenv.username = "user";
	scriptenv.hostname = "host.example.com";
	scriptenv.postmaster_address = "postmaster@example.com";
	scriptenv.smtp_open = NULL;
	scriptenv.smtp_close = NULL;
	scriptenv.duplicate_mark = NULL;
	scriptenv.duplicate_check = NULL;
	scriptenv.user = renv->scriptenv->user;
	scriptenv.trace_stream = renv->scriptenv->trace_stream;	
	scriptenv.trace_config = renv->scriptenv->trace_config;

	/* Start execution */

	mscript = sieve_multiscript_start_execute(svinst, renv->msgdata, &scriptenv);

	/* Execute scripts before main script */

	scripts = array_get(scriptfiles, &count);

	for ( i = 0; i < count && more; i++ ) {
		struct sieve_binary *sbin = NULL;
		const char *script = scripts[i];
		bool final = ( i == count - 1 );

		/* Open */
	
		if ( (sbin=_testsuite_script_compile(renv, script)) == NULL ) {
			result = FALSE;
			break;
		}

		/* Execute */

		sieve_runtime_trace(renv, SIEVE_TRLVL_TESTS, "run script `%s'", script);

		more = sieve_multiscript_run(mscript, sbin, testsuite_log_ehandler, final);

		sieve_close(&sbin);
	}

	return ( sieve_multiscript_finish(&mscript, testsuite_log_ehandler, NULL) > 0
		&& result );
}