/* -*- mode: C; c-basic-offset: 4 -*- */
#ident "Copyright (c) 2007 Tokutek Inc.  All rights reserved."
#include "test.h"


// make stdlib define unsetenv()
#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif

/* Do we open directories with same priority as BDB? i.e. with home, without home, with DB_USE_ENVIRON/etc.. */
#include <limits.h>
#include <stdio.h>
#include <assert.h>
#include <db.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>

#define CKERR(r) \
do {                                                                                                        \
    if (r!=0) fprintf(stderr, "%s:%d error %d %s\n", __FILE__, __LINE__, r, db_strerror(r)); assert(r==0);  \
} while (0)

// ENVDIR is defined in the Makefile

#define DB_HOME "DB_HOME"
#define DBNAME "test.db"

char* db_dir;
char db_name[PATH_MAX];
int extra_flags;
char* home;
BOOL inside_env = FALSE;


static void
reinit_config (int set_home, int set_DB_ENVIRON, int set_DB_HOME) {
    int r = 0;
    //Return to base dir
    if (inside_env) {
        r = chdir("../"); CKERR(r);
    }

    r = system("rm -rf " ENVDIR);          assert(r == 0);
    r = toku_os_mkdir(ENVDIR, S_IRWXU+S_IRWXG+S_IRWXO);               assert(r == 0);
    r = chdir(ENVDIR);                     assert(r == 0);
    inside_env = TRUE;
    unsetenv(DB_HOME);

    if (set_home) {
        db_dir = "home";
        r = toku_os_mkdir(db_dir, S_IRWXU+S_IRWXG+S_IRWXO);        assert(r == 0);
    }
    else if (set_DB_ENVIRON && set_DB_HOME) {
        db_dir = "DB_HOME";
        r = toku_os_mkdir(db_dir, S_IRWXU+S_IRWXG+S_IRWXO);        assert(r == 0);
    }
    else db_dir = ".";
    
    if (set_home) home = "home"; else home = NULL;
    if (set_DB_ENVIRON) extra_flags = DB_USE_ENVIRON; else extra_flags = 0;
    if (set_DB_HOME) {r = setenv(DB_HOME, DB_HOME, 1);assert(r == 0);}

}

int
test_main(int argc, const char *argv[]) {
    parse_args(argc, argv);
    DB_ENV *env;
    DB_TXN * const null_txn = 0;
    DB *db;
    int r;
    int i;
    
    for (i = 0; i < 8; i++) {
        int set_home = i & 0x1;
        int set_DB_ENVIRON = i & 0x2;
        int set_DB_HOME = i & 0x4;
        
        reinit_config(set_home, set_DB_ENVIRON, set_DB_HOME);
        r = snprintf(db_name, sizeof(db_name), "%s/%s", db_dir, DBNAME);
        assert(r < (int)sizeof(db_name));
        assert(r >= 0);
        
        r = db_env_create(&env, 0);
        CKERR(r);
        
        r = env->open(env, home, DB_CREATE|DB_PRIVATE|DB_INIT_MPOOL|extra_flags, 0);
// BDB does not check for this. TDB does more error checking.
#ifdef USE_TDB
        if (set_home && set_DB_ENVIRON) {
            assert(r == EINVAL);
            goto cleanup;
        }
        else
#endif
            CKERR(r);
        
        
        r = db_create(&db, env, 0);
        CKERR(r);

        r = db->open(db, null_txn, DBNAME, NULL, DB_BTREE, DB_CREATE, 0666);
        CKERR(r);

        r = db->close(db, 0);
        CKERR(r);

        //Verify it went in the right directory.
    	{
        	toku_struct_stat buf;
        	r = toku_stat(db_name, &buf);
        	CKERR(r);
        }
#ifdef USE_TDB
cleanup:
#endif
        r = env->close(env, 0);
        CKERR(r);        
    }

    return 0;
}
