<commit_before>// preliminary
// Part of support library for djinni4python, handwritten

#include <stdio.h> // for debugging
#include "wrapper_marshal.hpp"
#include "thread_local.hpp"
#include "../djinni_common.hpp"
#include <string>
#include <iostream> // for debugging

using namespace djinni;
using namespace djinni::optionals;
using std::optional;
using std::nullopt;

// Helpers to convert from a 'handle type' to a 'optional-handle type' or the other way around
// Useful in generated code, when marshaling and unmarshaling optional structured types, as it helps differentiate
// which overload of a toCpp, fromCpp function to be used
Handle<DjinniOptionalObjectHandle> optionals::toOptionalHandle(Handle<DjinniObjectHandle> handle,
                                                                         DeleterFn<DjinniOptionalObjectHandle> deletefn) {
    return Handle<DjinniOptionalObjectHandle>((DjinniOptionalObjectHandle *) handle.release(), deletefn);
}

Handle<DjinniObjectHandle> optionals::fromOptionalHandle(Handle<DjinniOptionalObjectHandle> handle,
                                                                   DeleterFn<DjinniObjectHandle> deletefn) {
    return Handle<DjinniObjectHandle>((DjinniObjectHandle *) handle.release(), deletefn);
}

Handle<DjinniOptionalRecordHandle> optionals::toOptionalHandle(Handle<DjinniRecordHandle> handle,
                                                                         DeleterFn<DjinniOptionalRecordHandle> deletefn) {
    return Handle<DjinniOptionalRecordHandle>((DjinniOptionalRecordHandle *) handle.release(), deletefn);

}

Handle<DjinniRecordHandle> optionals::fromOptionalHandle(Handle<DjinniOptionalRecordHandle> handle,
                                                                   DeleterFn<DjinniRecordHandle> deletefn) {
    return Handle<DjinniRecordHandle>((DjinniRecordHandle *) handle.release(), deletefn);
}

// Support for Handling Exceptions
static CreateExceptionFnPtr s_djinni_create_py_from_cpp_exception;
static DeleteExceptionFnPtr s_djinni_exception___delete;

// Structure holding current exception, if any
struct ExceptionState {
    static djinni::Handle<DjinniPythonExceptionHandle> newHandle(DjinniPythonExceptionHandle * c_ptr) {
        return djinni::Handle<DjinniPythonExceptionHandle>(c_ptr, s_djinni_exception___delete);
    }

    djinni::Handle<DjinniPythonExceptionHandle> takeException() {
        auto aux = std::move(handle);
        handle = nullptr;
        return aux;
    }

    djinni::Handle<DjinniPythonExceptionHandle> handle;
};

// Current exception state
static djinni::support_lib::ThreadLocal<ExceptionState> s_exception_state;

// to be called from Python
void djinni_create_and_set_cpp_from_py_exception(DjinniPythonExceptionHandle * py_e_handle) {
    s_exception_state.get().handle = ExceptionState::newHandle(py_e_handle);
}

void _djinni_add_callback_create_py_from_cpp_exception(CreateExceptionFnPtr fct_ptr) {
    s_djinni_create_py_from_cpp_exception = fct_ptr;
}
void _djinni_add_callback_exception___delete(DeleteExceptionFnPtr fct_ptr) {
    s_djinni_exception___delete = fct_ptr;
}

void djinni::cw_default_throw_exception(djinni::Handle<DjinniPythonExceptionHandle> e_handle) {
        throw djinni::py_exception(std::move(e_handle));
}

DJINNI_WEAK_DEFINITION
void djinni::cw_throw_exception(djinni::Handle<DjinniPythonExceptionHandle> e_handle) {
     cw_default_throw_exception(std::move(e_handle));
}

// to be called from cpp to allow cpp impl to know about pyhton exception
void djinni::cw_throw_if_pending() {
    auto e_handle = s_exception_state.get().takeException();

    if (e_handle) {
        cw_throw_exception(std::move(e_handle));
    }
}

djinni::Handle<DjinniPythonExceptionHandle> djinni::cw_default_get_py_exception(const std::exception_ptr & e_ptr) noexcept {
    try {
        if (e_ptr) {
            std::rethrow_exception(e_ptr);
        }
    } catch (djinni::py_exception & py_e) { // exception generated by user python code
         return py_e.takePyException();
    } catch (const std::exception & e) { // exception generated by user cpp code
        auto e_mesg = DjinniString::fromCpp(e.what());
        return ExceptionState::newHandle(s_djinni_create_py_from_cpp_exception(e_mesg.release()));
    }
    assert(false);
}

// The argument is an exception_ptr for either a std::exception or a subclass of std::exception called py_exception
// Creates or retrieves a handle to a python exception from the exception_ptr
DJINNI_WEAK_DEFINITION
djinni::Handle<DjinniPythonExceptionHandle> djinni::cw_get_py_exception(const std::exception_ptr & e_ptr) noexcept {
    return cw_default_get_py_exception(e_ptr);
}

// Create a python exception from the exception pointer, and set it in s_exception_state to allow Python to
// notice an exception was thrown
// The argument is an exception_ptr for either a std::exception or a subclass of std::exception called py_exception
void djinni::cw_set_pending_exception(const std::exception_ptr & e_ptr) {
    s_exception_state.get().handle = cw_get_py_exception(e_ptr);
}

DjinniPythonExceptionHandle * djinni_from_python_check_and_clear_exception() {
    if (s_exception_state.get().handle) {
        return s_exception_state.get().takeException().release();
    }
    return nullptr;
}

// DJINNI PRIMITIVE OPTIONALS
// OPTIONAL INTEGERS
DjinniBoxedI8 * create_djinni_boxed_i8(int8_t pyopt) {
    return DjinniBoxedI8::newOptional(pyopt).release();
}
void delete_djinni_boxed_i8(DjinniBoxedI8 * dopt) {
    delete dopt;
}
int8_t get_djinni_boxed_i8_data(DjinniBoxedI8 * dopt) {
    return dopt->m_data;
}

DjinniBoxedI16 * create_djinni_boxed_i16(int16_t pyopt) {
    return DjinniBoxedI16::newOptional(pyopt).release();
}
void delete_djinni_boxed_i16(DjinniBoxedI16 * dopt) {
    delete dopt;
}
int16_t get_djinni_boxed_i16_data(DjinniBoxedI16 * dopt) {
    return dopt->m_data;
}

DjinniBoxedI32 * create_djinni_boxed_i32(int32_t pyopt) {
    return DjinniBoxedI32::newOptional(pyopt).release();
}
void delete_djinni_boxed_i32(DjinniBoxedI32 * dopt) {
    delete dopt;
}
int32_t get_djinni_boxed_i32_data(DjinniBoxedI32 * dopt) {
    return dopt->m_data;
}

DjinniBoxedI64 * create_djinni_boxed_i64(int64_t pyopt) {
    return DjinniBoxedI64::newOptional(pyopt).release();
}
void delete_djinni_boxed_i64(DjinniBoxedI64 * dopt) {
    delete dopt;
}
int64_t get_djinni_boxed_i64_data(DjinniBoxedI64 * dopt) {
    return dopt->m_data;
}

// OPTIONAL FLOATING POINTS
DjinniBoxedF32 * create_djinni_boxed_f32(float pyopt) {
    return DjinniBoxedF32::newOptional(pyopt).release();
}
void delete_djinni_boxed_f32(DjinniBoxedF32 * dopt) {
    delete dopt;
}
float get_djinni_boxed_f32_data(DjinniBoxedF32 * dopt) {
    return dopt->m_data;
}

DjinniBoxedF64 * create_djinni_boxed_f64(double pyopt) {
    return DjinniBoxedF64::newOptional(pyopt).release();
}
void delete_djinni_boxed_f64(DjinniBoxedF64 * dopt) {
    delete dopt;
}
double get_djinni_boxed_f64_data(DjinniBoxedF64 * dopt) {
    return dopt->m_data;
}

// OPTIONAL BOOL
DjinniBoxedBool * create_djinni_boxed_bool(bool pyopt) {
    return DjinniBoxedBool::newOptional(pyopt).release();
}
void delete_djinni_boxed_bool(DjinniBoxedBool * dopt) {
    delete dopt;
}
bool get_djinni_boxed_bool_data(DjinniBoxedBool * dopt) {
    return dopt->m_data;
}

// DJINNI STRING
DjinniString::DjinniString(std::string s) {
    this->cppstr = std::move(s);
}

DjinniString * create_djinni_string(const char * s, size_t len) {
    return DjinniString::fromCpp(std::string(s,len)).release();
}

void delete_djinni_string(DjinniString * ss) {
    delete ss;
}

const char * get_djinni_string_chars(const DjinniString * ds) {
    return ds->cppstr.c_str();
}

size_t get_djinni_string_len(const DjinniString * ds) {
    return ds->cppstr.length();
}

std::unique_ptr<DjinniString> DjinniString::fromCpp(std::string cppstr) {
     return std::unique_ptr<DjinniString>(new DjinniString(std::move(cppstr)));
}

std::string DjinniString::toCpp(std::unique_ptr<DjinniString> ds) {
    return std::move(ds->cppstr);
}

// OPTIONAL DJINNI STRING
optional<std::string> DjinniOptionalString::toCpp(std::unique_ptr<DjinniString> ds) {
    if (ds) {
        return std::move(ds->cppstr);
    }
    return nullopt;
}

std::unique_ptr<DjinniString> DjinniOptionalString::fromCpp(optional<std::string> s) {
    if (s) {
        return DjinniString::fromCpp(std::move(* s));
    }
    return nullptr;
}

// DJINNI BINARY
DjinniBinary::DjinniBinary(std::vector<uint8_t> b) {
    this->cppbinary = std::move(b);
}

DjinniBinary * create_djinni_binary(const uint8_t * b, size_t len) {
    return DjinniBinary::fromCpp(std::vector<uint8_t>(b, b+len)).release();
}

void delete_djinni_binary(DjinniBinary * db) {
    delete db;
}

const uint8_t * get_djinni_binary_uint8s(const DjinniBinary * db) {
    return db->cppbinary.data();
}

size_t get_djinni_binary_len(const DjinniBinary * db) {
  return db->cppbinary.size();
}

std::unique_ptr<DjinniBinary> DjinniBinary::fromCpp(std::vector<uint8_t> cppbinary) {
     return std::unique_ptr<DjinniBinary>(new DjinniBinary(std::move(cppbinary)));
}

std::vector<uint8_t> DjinniBinary::toCpp(std::unique_ptr<DjinniBinary> db) {
    return std::move(db->cppbinary);
}

// OPTIONAL DJINNI BINARY
std::unique_ptr<DjinniBinary> DjinniOptionalBinary::fromCpp(optional<std::vector<uint8_t>> cppbinary) {
    if (cppbinary) {
        return DjinniBinary::fromCpp(std::move(* cppbinary));
    }
   return nullptr;
}

optional<std::vector<uint8_t>> DjinniOptionalBinary::toCpp(std::unique_ptr<DjinniBinary> db) {
    if (db) {
        return std::move(db->cppbinary);
    }
    return nullopt;
}

// DJINNI DATE
auto static const POSIX_EPOCH = std::chrono::system_clock::from_time_t(0);
std::chrono::system_clock::time_point DjinniDate::toCpp(uint64_t duration) {
    return POSIX_EPOCH + std::chrono::milliseconds{duration};
}

uint64_t DjinniDate::fromCpp(std::chrono::system_clock::time_point date) {
    return std::chrono::duration_cast<std::chrono::milliseconds>(date - POSIX_EPOCH).count();
}

// OPTIONAL DJINNI DATE
std::optional<std::chrono::system_clock::time_point>
DjinniBoxedDate::toCpp(std::unique_ptr<DjinniBoxedDate> dopt) {
    if (!dopt) {
        return nullopt;
    }
    return DjinniDate::toCpp(dopt->m_data);
}

std::unique_ptr<DjinniBoxedDate>
DjinniBoxedDate::fromCpp(std::optional<std::chrono::system_clock::time_point> dopt) {
    if (!dopt) {
        return nullptr;
    }
    return newOptional(*dopt);
}

std::unique_ptr<DjinniBoxedDate>
DjinniBoxedDate::newOptional(std::chrono::system_clock::time_point data) {
    return std::unique_ptr<DjinniBoxedDate>(new DjinniBoxedDate(DjinniDate::fromCpp(data)));
}

DjinniBoxedDate * create_djinni_boxed_date(uint64_t pyopt) {
    return DjinniBoxedDate::newOptional(DjinniDate::toCpp(pyopt)).release();
}

void delete_djinni_boxed_date(DjinniBoxedDate * dopt) {
    delete dopt;
}

uint64_t get_djinni_boxed_date_data(DjinniBoxedDate * dopt) {
    return dopt->m_data;
}
<commit_msg>Avoid warning of non returning function (#34)<commit_after>// preliminary
// Part of support library for djinni4python, handwritten

#include <stdio.h> // for debugging
#include "wrapper_marshal.hpp"
#include "thread_local.hpp"
#include "../djinni_common.hpp"
#include <string>
#include <iostream> // for debugging

using namespace djinni;
using namespace djinni::optionals;
using std::optional;
using std::nullopt;

// Helpers to convert from a 'handle type' to a 'optional-handle type' or the other way around
// Useful in generated code, when marshaling and unmarshaling optional structured types, as it helps differentiate
// which overload of a toCpp, fromCpp function to be used
Handle<DjinniOptionalObjectHandle> optionals::toOptionalHandle(Handle<DjinniObjectHandle> handle,
                                                                         DeleterFn<DjinniOptionalObjectHandle> deletefn) {
    return Handle<DjinniOptionalObjectHandle>((DjinniOptionalObjectHandle *) handle.release(), deletefn);
}

Handle<DjinniObjectHandle> optionals::fromOptionalHandle(Handle<DjinniOptionalObjectHandle> handle,
                                                                   DeleterFn<DjinniObjectHandle> deletefn) {
    return Handle<DjinniObjectHandle>((DjinniObjectHandle *) handle.release(), deletefn);
}

Handle<DjinniOptionalRecordHandle> optionals::toOptionalHandle(Handle<DjinniRecordHandle> handle,
                                                                         DeleterFn<DjinniOptionalRecordHandle> deletefn) {
    return Handle<DjinniOptionalRecordHandle>((DjinniOptionalRecordHandle *) handle.release(), deletefn);

}

Handle<DjinniRecordHandle> optionals::fromOptionalHandle(Handle<DjinniOptionalRecordHandle> handle,
                                                                   DeleterFn<DjinniRecordHandle> deletefn) {
    return Handle<DjinniRecordHandle>((DjinniRecordHandle *) handle.release(), deletefn);
}

// Support for Handling Exceptions
static CreateExceptionFnPtr s_djinni_create_py_from_cpp_exception;
static DeleteExceptionFnPtr s_djinni_exception___delete;

// Structure holding current exception, if any
struct ExceptionState {
    static djinni::Handle<DjinniPythonExceptionHandle> newHandle(DjinniPythonExceptionHandle * c_ptr) {
        return djinni::Handle<DjinniPythonExceptionHandle>(c_ptr, s_djinni_exception___delete);
    }

    djinni::Handle<DjinniPythonExceptionHandle> takeException() {
        auto aux = std::move(handle);
        handle = nullptr;
        return aux;
    }

    djinni::Handle<DjinniPythonExceptionHandle> handle;
};

// Current exception state
static djinni::support_lib::ThreadLocal<ExceptionState> s_exception_state;

// to be called from Python
void djinni_create_and_set_cpp_from_py_exception(DjinniPythonExceptionHandle * py_e_handle) {
    s_exception_state.get().handle = ExceptionState::newHandle(py_e_handle);
}

void _djinni_add_callback_create_py_from_cpp_exception(CreateExceptionFnPtr fct_ptr) {
    s_djinni_create_py_from_cpp_exception = fct_ptr;
}
void _djinni_add_callback_exception___delete(DeleteExceptionFnPtr fct_ptr) {
    s_djinni_exception___delete = fct_ptr;
}

void djinni::cw_default_throw_exception(djinni::Handle<DjinniPythonExceptionHandle> e_handle) {
        throw djinni::py_exception(std::move(e_handle));
}

DJINNI_WEAK_DEFINITION
void djinni::cw_throw_exception(djinni::Handle<DjinniPythonExceptionHandle> e_handle) {
     cw_default_throw_exception(std::move(e_handle));
}

// to be called from cpp to allow cpp impl to know about pyhton exception
void djinni::cw_throw_if_pending() {
    auto e_handle = s_exception_state.get().takeException();

    if (e_handle) {
        cw_throw_exception(std::move(e_handle));
    }
}

djinni::Handle<DjinniPythonExceptionHandle> djinni::cw_default_get_py_exception(const std::exception_ptr & e_ptr) noexcept {
    try {
        if (e_ptr) {
            std::rethrow_exception(e_ptr);
        }
    } catch (djinni::py_exception & py_e) { // exception generated by user python code
         return py_e.takePyException();
    } catch (const std::exception & e) { // exception generated by user cpp code
        auto e_mesg = DjinniString::fromCpp(e.what());
        return ExceptionState::newHandle(s_djinni_create_py_from_cpp_exception(e_mesg.release()));
    }
    assert(false);
    return {}; //avoid compiler warning not returning anything
}

// The argument is an exception_ptr for either a std::exception or a subclass of std::exception called py_exception
// Creates or retrieves a handle to a python exception from the exception_ptr
DJINNI_WEAK_DEFINITION
djinni::Handle<DjinniPythonExceptionHandle> djinni::cw_get_py_exception(const std::exception_ptr & e_ptr) noexcept {
    return cw_default_get_py_exception(e_ptr);
}

// Create a python exception from the exception pointer, and set it in s_exception_state to allow Python to
// notice an exception was thrown
// The argument is an exception_ptr for either a std::exception or a subclass of std::exception called py_exception
void djinni::cw_set_pending_exception(const std::exception_ptr & e_ptr) {
    s_exception_state.get().handle = cw_get_py_exception(e_ptr);
}

DjinniPythonExceptionHandle * djinni_from_python_check_and_clear_exception() {
    if (s_exception_state.get().handle) {
        return s_exception_state.get().takeException().release();
    }
    return nullptr;
}

// DJINNI PRIMITIVE OPTIONALS
// OPTIONAL INTEGERS
DjinniBoxedI8 * create_djinni_boxed_i8(int8_t pyopt) {
    return DjinniBoxedI8::newOptional(pyopt).release();
}
void delete_djinni_boxed_i8(DjinniBoxedI8 * dopt) {
    delete dopt;
}
int8_t get_djinni_boxed_i8_data(DjinniBoxedI8 * dopt) {
    return dopt->m_data;
}

DjinniBoxedI16 * create_djinni_boxed_i16(int16_t pyopt) {
    return DjinniBoxedI16::newOptional(pyopt).release();
}
void delete_djinni_boxed_i16(DjinniBoxedI16 * dopt) {
    delete dopt;
}
int16_t get_djinni_boxed_i16_data(DjinniBoxedI16 * dopt) {
    return dopt->m_data;
}

DjinniBoxedI32 * create_djinni_boxed_i32(int32_t pyopt) {
    return DjinniBoxedI32::newOptional(pyopt).release();
}
void delete_djinni_boxed_i32(DjinniBoxedI32 * dopt) {
    delete dopt;
}
int32_t get_djinni_boxed_i32_data(DjinniBoxedI32 * dopt) {
    return dopt->m_data;
}

DjinniBoxedI64 * create_djinni_boxed_i64(int64_t pyopt) {
    return DjinniBoxedI64::newOptional(pyopt).release();
}
void delete_djinni_boxed_i64(DjinniBoxedI64 * dopt) {
    delete dopt;
}
int64_t get_djinni_boxed_i64_data(DjinniBoxedI64 * dopt) {
    return dopt->m_data;
}

// OPTIONAL FLOATING POINTS
DjinniBoxedF32 * create_djinni_boxed_f32(float pyopt) {
    return DjinniBoxedF32::newOptional(pyopt).release();
}
void delete_djinni_boxed_f32(DjinniBoxedF32 * dopt) {
    delete dopt;
}
float get_djinni_boxed_f32_data(DjinniBoxedF32 * dopt) {
    return dopt->m_data;
}

DjinniBoxedF64 * create_djinni_boxed_f64(double pyopt) {
    return DjinniBoxedF64::newOptional(pyopt).release();
}
void delete_djinni_boxed_f64(DjinniBoxedF64 * dopt) {
    delete dopt;
}
double get_djinni_boxed_f64_data(DjinniBoxedF64 * dopt) {
    return dopt->m_data;
}

// OPTIONAL BOOL
DjinniBoxedBool * create_djinni_boxed_bool(bool pyopt) {
    return DjinniBoxedBool::newOptional(pyopt).release();
}
void delete_djinni_boxed_bool(DjinniBoxedBool * dopt) {
    delete dopt;
}
bool get_djinni_boxed_bool_data(DjinniBoxedBool * dopt) {
    return dopt->m_data;
}

// DJINNI STRING
DjinniString::DjinniString(std::string s) {
    this->cppstr = std::move(s);
}

DjinniString * create_djinni_string(const char * s, size_t len) {
    return DjinniString::fromCpp(std::string(s,len)).release();
}

void delete_djinni_string(DjinniString * ss) {
    delete ss;
}

const char * get_djinni_string_chars(const DjinniString * ds) {
    return ds->cppstr.c_str();
}

size_t get_djinni_string_len(const DjinniString * ds) {
    return ds->cppstr.length();
}

std::unique_ptr<DjinniString> DjinniString::fromCpp(std::string cppstr) {
     return std::unique_ptr<DjinniString>(new DjinniString(std::move(cppstr)));
}

std::string DjinniString::toCpp(std::unique_ptr<DjinniString> ds) {
    return std::move(ds->cppstr);
}

// OPTIONAL DJINNI STRING
optional<std::string> DjinniOptionalString::toCpp(std::unique_ptr<DjinniString> ds) {
    if (ds) {
        return std::move(ds->cppstr);
    }
    return nullopt;
}

std::unique_ptr<DjinniString> DjinniOptionalString::fromCpp(optional<std::string> s) {
    if (s) {
        return DjinniString::fromCpp(std::move(* s));
    }
    return nullptr;
}

// DJINNI BINARY
DjinniBinary::DjinniBinary(std::vector<uint8_t> b) {
    this->cppbinary = std::move(b);
}

DjinniBinary * create_djinni_binary(const uint8_t * b, size_t len) {
    return DjinniBinary::fromCpp(std::vector<uint8_t>(b, b+len)).release();
}

void delete_djinni_binary(DjinniBinary * db) {
    delete db;
}

const uint8_t * get_djinni_binary_uint8s(const DjinniBinary * db) {
    return db->cppbinary.data();
}

size_t get_djinni_binary_len(const DjinniBinary * db) {
  return db->cppbinary.size();
}

std::unique_ptr<DjinniBinary> DjinniBinary::fromCpp(std::vector<uint8_t> cppbinary) {
     return std::unique_ptr<DjinniBinary>(new DjinniBinary(std::move(cppbinary)));
}

std::vector<uint8_t> DjinniBinary::toCpp(std::unique_ptr<DjinniBinary> db) {
    return std::move(db->cppbinary);
}

// OPTIONAL DJINNI BINARY
std::unique_ptr<DjinniBinary> DjinniOptionalBinary::fromCpp(optional<std::vector<uint8_t>> cppbinary) {
    if (cppbinary) {
        return DjinniBinary::fromCpp(std::move(* cppbinary));
    }
   return nullptr;
}

optional<std::vector<uint8_t>> DjinniOptionalBinary::toCpp(std::unique_ptr<DjinniBinary> db) {
    if (db) {
        return std::move(db->cppbinary);
    }
    return nullopt;
}

// DJINNI DATE
auto static const POSIX_EPOCH = std::chrono::system_clock::from_time_t(0);
std::chrono::system_clock::time_point DjinniDate::toCpp(uint64_t duration) {
    return POSIX_EPOCH + std::chrono::milliseconds{duration};
}

uint64_t DjinniDate::fromCpp(std::chrono::system_clock::time_point date) {
    return std::chrono::duration_cast<std::chrono::milliseconds>(date - POSIX_EPOCH).count();
}

// OPTIONAL DJINNI DATE
std::optional<std::chrono::system_clock::time_point>
DjinniBoxedDate::toCpp(std::unique_ptr<DjinniBoxedDate> dopt) {
    if (!dopt) {
        return nullopt;
    }
    return DjinniDate::toCpp(dopt->m_data);
}

std::unique_ptr<DjinniBoxedDate>
DjinniBoxedDate::fromCpp(std::optional<std::chrono::system_clock::time_point> dopt) {
    if (!dopt) {
        return nullptr;
    }
    return newOptional(*dopt);
}

std::unique_ptr<DjinniBoxedDate>
DjinniBoxedDate::newOptional(std::chrono::system_clock::time_point data) {
    return std::unique_ptr<DjinniBoxedDate>(new DjinniBoxedDate(DjinniDate::fromCpp(data)));
}

DjinniBoxedDate * create_djinni_boxed_date(uint64_t pyopt) {
    return DjinniBoxedDate::newOptional(DjinniDate::toCpp(pyopt)).release();
}

void delete_djinni_boxed_date(DjinniBoxedDate * dopt) {
    delete dopt;
}

uint64_t get_djinni_boxed_date_data(DjinniBoxedDate * dopt) {
    return dopt->m_data;
}
<|endoftext|>


<commit_before><commit_msg>Updating context-ls: listProviders -> providers.<commit_after><|endoftext|>


<commit_before>/*=========================================================================

  Program:   ORFEO Toolbox
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) Centre National d'Etudes Spatiales. All rights reserved.
  See OTBCopyright.txt for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notices for more information.

=========================================================================*/
#include <set>
#include "otbImage.h"
#include "otbVectorImage.h"

#include "itkImageRegionIterator.h"
#include "itkImageRegionReverseIterator.h"
#include "itkImageRandomIteratorWithIndex.h"
#include "itkImageScanlineIterator.h"
#include "itkImageRandomNonRepeatingIteratorWithIndex.h"
#include "otbSubsampledImageRegionIterator.h"

#include "otbMaskedIteratorDecorator.h"

// Generate a test image of specified size and value
template <typename ImageType>
typename ImageType::Pointer GetTestImage(itk::SizeValueType fillSize, const typename ImageType::PixelType& value, unsigned int nbBand=1)
{
  typename ImageType::Pointer image = ImageType::New();
  typename ImageType::SizeType size;
  size.Fill(fillSize);

  typename ImageType::RegionType region;
  region.SetSize(size);

  image->SetNumberOfComponentsPerPixel(nbBand);
  image->SetRegions(region);
  image->Allocate();
  image->FillBuffer(value);
  return image;
}

// Fill half of the pixels with a value
// Used for generating a test mask
template <typename ImageType>
void FillHalf(typename ImageType::Pointer image, const typename ImageType::RegionType& region, const typename ImageType::PixelType& value)
{
  itk::ImageRegionIterator<ImageType> it(image, region);
  unsigned int count = 0;
  for(it.GoToBegin(); !it.IsAtEnd(); ++it, ++count)
  {
    if (count % 2 == 0)
    {
      it.Set(value);
    }
  }
}

// Test template instanciation
int otbMaskedIteratorDecoratorNew(int itkNotUsed(argc), char * itkNotUsed(argv) [])
{
  typedef otb::Image<double, 2> ImageType;
  ImageType::Pointer image = GetTestImage<ImageType>(10, 10);
  ImageType::Pointer mask = GetTestImage<ImageType>(10, 0);
  ImageType::RegionType region(image->GetLargestPossibleRegion());

  otb::MaskedIteratorDecorator<itk::ImageRegionIterator<ImageType> > it(mask, image, region);
  return EXIT_SUCCESS;
}

// ---------------------- Initialization code ----------------------------------
template <typename IteratorType>
void
InitializeIterator(IteratorType&, typename IteratorType::RegionType)
{
  // by default : nothing to do
}

// specialization for otb::SubsampledImageRegionIterator<otb::Image<double, 2> >
template <>
void
InitializeIterator< otb::SubsampledImageRegionIterator< otb::Image<double, 2> > >(
  otb::SubsampledImageRegionIterator< otb::Image<double, 2> >& it,
  typename otb::SubsampledImageRegionIterator<otb::Image<double, 2> >::RegionType)
{
  it.SetSubsampleFactor(2);
}

// -------------------------- ForwardTest --------------------------------------
// Function to test the forward iteration interface
template <typename IteratorType, typename MaskIteratorType>
int ForwardTest(typename MaskIteratorType::ImageType::Pointer mask, typename IteratorType::ImageType::Pointer image, typename IteratorType::ImageType::RegionType region)
{
  otb::MaskedIteratorDecorator<IteratorType,MaskIteratorType> it(mask, image, region);

  // specific initialization code
  InitializeIterator<IteratorType>(it.GetImageIterator(),region);
  if (it.HasMask())
    {
    InitializeIterator<MaskIteratorType>(it.GetMaskIterator(),region);
    }

  it.GoToBegin();
  if (!it.IsAtBegin()) {return 1;}

  unsigned int loopCount = 0;
  for(; !it.IsAtEnd(); ++it)
  {
    if (loopCount != 0 && it.IsAtBegin()) {return 2;}
    if (it.IsAtEnd()) {return 3;}

    //it.Set(it.Value() * 0.42);

    loopCount += 1;
  }

  if(!it.IsAtEnd()) {return 4;}
  return 0;
}

// -------------------------- ReverseTest --------------------------------------
// Test reverse iteration interface
template <typename IteratorType, typename MaskIteratorType>
int ReverseTest(typename MaskIteratorType::ImageType::Pointer mask, typename IteratorType::ImageType::Pointer image, typename IteratorType::ImageType::RegionType region)
{
  otb::MaskedIteratorDecorator<IteratorType,MaskIteratorType> it(mask, image, region);

  // specific initialization code
  InitializeIterator<IteratorType>(it.GetImageIterator(),region);
  if (it.HasMask())
    {
    InitializeIterator<MaskIteratorType>(it.GetMaskIterator(),region);
    }

  it.GoToEnd();
  if (!it.IsAtEnd()) {return 1;}

  bool beginReached = false;
  while (!it.IsAtBegin())
    {
    --it;
    if (it.IsAtEnd()) {return 2;}
    if (beginReached)
      {
      return 3;
      }
    if (it.IsAtBegin())
      {
      beginReached = true;
      }
    }

  if(!it.IsAtBegin()) {return 4;}
  return 0;
}

// -------------------------- BijectiveTest --------------------------------------
// Check bijection between iterated and non masked
// i.e all locations where mask value != 0 are in the iteration (injection)
// and mask value != 0 at all iteration locations (surjection)
// Templated to test decoration of different iterator types
template <typename IteratorType, typename MaskIteratorType>
int BijectiveTest(typename MaskIteratorType::ImageType::Pointer mask, typename IteratorType::ImageType::Pointer image, typename IteratorType::ImageType::RegionType region)
{
  otb::MaskedIteratorDecorator<IteratorType,MaskIteratorType> itDecorated(mask, image, region);
  IteratorType it(image, region);

  // specific initialization code
  InitializeIterator<IteratorType>(itDecorated.GetImageIterator(),region);
  InitializeIterator<IteratorType>(it,region);
  if (itDecorated.HasMask())
    {
    InitializeIterator<MaskIteratorType>(itDecorated.GetMaskIterator(),region);
    }

  it.GoToBegin();
  itDecorated.GoToBegin();

  // Find the non maked begin for the image iterator
  if (itDecorated.HasMask())
    {
    while (mask->GetPixel(it.GetIndex()) == 0 && !it.IsAtEnd())
      {
      ++it;
      }
    }

  // Begins are the same
  if (!(it.GetIndex() == itDecorated.GetIndex()
     && it.GetIndex() == itDecorated.GetImageIterator().GetIndex()))
  {
    return 1;
  }

  if (itDecorated.HasMask() && it.GetIndex() != itDecorated.GetMaskIterator().GetIndex())
    {
    return 1;
    }

  // Advance both and check
  while (!it.IsAtEnd() && !itDecorated.IsAtEnd())
  {
    // Iteration locations are the same
    if (!(it.GetIndex() == itDecorated.GetIndex()
       && it.GetIndex() == itDecorated.GetImageIterator().GetIndex()))
      {
      return 2;
      }
    if (itDecorated.HasMask() && it.GetIndex() != itDecorated.GetMaskIterator().GetIndex())
      {
      return 2;
      }

    ++itDecorated;
    if (itDecorated.HasMask())
      {
      do
        {
        ++it;
        } while (mask->GetPixel(it.GetIndex()) == 0 && !it.IsAtEnd());
      }
    else
      {
      ++it;
      }
  }

  // Check IsAtEnd
  if (!(it.IsAtEnd() && itDecorated.IsAtEnd()))
  {
    return 3;
  }

  return 0;
}

// Multiplex to forward, reverse and bijection test
template <typename IteratorType, typename MaskIteratorType>
int TripleTest(typename IteratorType::ImageType::Pointer image,typename MaskIteratorType::ImageType::Pointer mask, typename IteratorType::ImageType::RegionType region)
{
  int ret;
  int retGlobal = EXIT_SUCCESS;

  ret = ForwardTest<IteratorType,MaskIteratorType>(mask, image, region);
  if (ret>0)
    {
    std::cout << "Forward(FAILED:"<<ret<<") ";
    retGlobal = EXIT_FAILURE;
    }

  ret = ReverseTest<IteratorType,MaskIteratorType>(mask, image, region);
  if (ret>0)
    {
    std::cout << "Reverse(FAILED:"<<ret<<") ";
    retGlobal = EXIT_FAILURE;
    }

  ret = BijectiveTest<IteratorType,MaskIteratorType>(mask, image, region);
  if (ret>0)
    {
    std::cout << "Bijective(FAILED:"<<ret<<") ";
    retGlobal = EXIT_FAILURE;
    }

  if (retGlobal == EXIT_SUCCESS)
    {
    std::cout << "PASSED";
    }
  return retGlobal;
}

// -------------------------- Nominal case -------------------------------------
int otbMaskedIteratorDecoratorNominal(int itkNotUsed(argc), char * itkNotUsed(argv) [])
{
  typedef otb::Image<double, 2> ImageType;
  ImageType::Pointer image = GetTestImage<ImageType>(10, 10);
  ImageType::Pointer mask = GetTestImage<ImageType>(10, 0);
  ImageType::RegionType region(image->GetLargestPossibleRegion());
  FillHalf<ImageType>(mask, region, 1);
  int ret;
  int retGlobal = EXIT_SUCCESS;

  std::cout << std::endl << "itk::ImageRegionIterator : ";
  ret = TripleTest< itk::ImageRegionIterator<ImageType>,
                    itk::ImageRegionIterator<ImageType> >(image, mask, region);
  retGlobal = (ret == EXIT_FAILURE ? EXIT_FAILURE : retGlobal);

  std::cout << std::endl << "itk::ImageRegionConstIterator : ";
  ret = TripleTest< itk::ImageRegionConstIterator<ImageType>,
                    itk::ImageRegionConstIterator<ImageType> >(image, mask, region);
  retGlobal = (ret == EXIT_FAILURE ? EXIT_FAILURE : retGlobal);

  // std::cout << std::endl << "otb::SubsampledImageRegionIterator : ";
  // ret = TripleTest< otb::SubsampledImageRegionIterator<ImageType>,
  //                   otb::SubsampledImageRegionIterator<ImageType> >(image, mask, region);
  // retGlobal = (ret == EXIT_FAILURE ? EXIT_FAILURE : retGlobal);

  return retGlobal;
}

// ------------------------ Degenerate cases -----------------------------------
int otbMaskedIteratorDecoratorDegenerate(int itkNotUsed(argc), char * itkNotUsed(argv) [])
{
  // Fully masked (0 everywhere)
  typedef otb::Image<double, 2> ImageType;
  ImageType::Pointer image = GetTestImage<ImageType>(10, 10);
  ImageType::Pointer mask = GetTestImage<ImageType>(10, 0);
  ImageType::RegionType region(image->GetLargestPossibleRegion());

  return TripleTest<itk::ImageRegionIterator<ImageType>,
                    itk::ImageRegionIterator<ImageType> >(image, mask, region);
}

// --------------------------- Extended cases ----------------------------------
int otbMaskedIteratorDecoratorExtended(int itkNotUsed(argc), char * itkNotUsed(argv) [])
{
  typedef otb::VectorImage<double, 2> ImageType;
  typedef otb::Image<unsigned char, 2> MaskType;
  otb::VectorImage<double, 2>::PixelType pixel(3);
  pixel.Fill(12);
  ImageType::Pointer image = GetTestImage<ImageType>(10,pixel ,3);
  MaskType::Pointer mask = GetTestImage<MaskType>(10, 0);
  ImageType::RegionType region(image->GetLargestPossibleRegion());
  FillHalf<MaskType>(mask, region, 1);
  int ret;
  int retGlobal = EXIT_SUCCESS;

  std::cout << std::endl << "itk::ImageRegionIterator : ";
  ret = TripleTest< itk::ImageRegionIterator<ImageType>,
                    itk::ImageRegionIterator<MaskType> >(image, mask, region);
  retGlobal = (ret == EXIT_FAILURE ? EXIT_FAILURE : retGlobal);

  std::cout << std::endl << "itk::ImageRegionConstIterator : ";
  ret = TripleTest< itk::ImageRegionConstIterator<ImageType>,
                    itk::ImageRegionConstIterator<MaskType> >(image, mask, region);
  retGlobal = (ret == EXIT_FAILURE ? EXIT_FAILURE : retGlobal);

  std::cout << std::endl << "itk::ImageRegionIterator without mask: ";
  ret = TripleTest< itk::ImageRegionIterator<ImageType>,
                    itk::ImageRegionIterator<MaskType> >(image, NULL, region);
  retGlobal = (ret == EXIT_FAILURE ? EXIT_FAILURE : retGlobal);

  std::cout << std::endl << "itk::ImageRegionConstIterator without mask: ";
  ret = TripleTest< itk::ImageRegionConstIterator<ImageType>,
                    itk::ImageRegionConstIterator<MaskType> >(image, NULL, region);
  retGlobal = (ret == EXIT_FAILURE ? EXIT_FAILURE : retGlobal);

  return retGlobal;
}

/* Other iterators potentially compatible:

Different constructor arguments than (image, region)
itk::PathIterator
itk::LineIterator
itk::SliceIterator
itk::NeighborhoodIterator

Needs initialization code:
itk::ImageRandomConstIteratorWithIndex
itk::ImageRandomIteratorWithIndex
itk::ImageRandomNonRepeatingConstIteratorWithIndex
itk::ImageRandomNonRepeatingIteratorWithIndex

otb::SubsampledImageRegionIterator  : GoToEnd is buggy !

Different iteration interface than normal iterators:
itk::ImageScanlineIterator
itk::ImageScanlineConstIterator

GoToEnd is not implemented
itk::ImageLinearIteratorWithIndex
itk::ReflectiveImageRegionIterator
itk::ImageRegionExclusionConstIteratorWithIndex
itk::ImageRegionIteratorWithIndex

Other problem:
itk::ImageRegionReverseIterator>() // IsAtEnd not a const method
otb::PolyLineImageIterator>() // header not found
itk::ImageRandomConstIteratorWithOnlyIndex>() // no Value method
*/
<commit_msg>COMP: wrong place for a typename (gcc 4.1.2)<commit_after>/*=========================================================================

  Program:   ORFEO Toolbox
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) Centre National d'Etudes Spatiales. All rights reserved.
  See OTBCopyright.txt for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notices for more information.

=========================================================================*/
#include <set>
#include "otbImage.h"
#include "otbVectorImage.h"

#include "itkImageRegionIterator.h"
#include "itkImageRegionReverseIterator.h"
#include "itkImageRandomIteratorWithIndex.h"
#include "itkImageScanlineIterator.h"
#include "itkImageRandomNonRepeatingIteratorWithIndex.h"
#include "otbSubsampledImageRegionIterator.h"

#include "otbMaskedIteratorDecorator.h"

// Generate a test image of specified size and value
template <typename ImageType>
typename ImageType::Pointer GetTestImage(itk::SizeValueType fillSize, const typename ImageType::PixelType& value, unsigned int nbBand=1)
{
  typename ImageType::Pointer image = ImageType::New();
  typename ImageType::SizeType size;
  size.Fill(fillSize);

  typename ImageType::RegionType region;
  region.SetSize(size);

  image->SetNumberOfComponentsPerPixel(nbBand);
  image->SetRegions(region);
  image->Allocate();
  image->FillBuffer(value);
  return image;
}

// Fill half of the pixels with a value
// Used for generating a test mask
template <typename ImageType>
void FillHalf(typename ImageType::Pointer image, const typename ImageType::RegionType& region, const typename ImageType::PixelType& value)
{
  itk::ImageRegionIterator<ImageType> it(image, region);
  unsigned int count = 0;
  for(it.GoToBegin(); !it.IsAtEnd(); ++it, ++count)
  {
    if (count % 2 == 0)
    {
      it.Set(value);
    }
  }
}

// Test template instanciation
int otbMaskedIteratorDecoratorNew(int itkNotUsed(argc), char * itkNotUsed(argv) [])
{
  typedef otb::Image<double, 2> ImageType;
  ImageType::Pointer image = GetTestImage<ImageType>(10, 10);
  ImageType::Pointer mask = GetTestImage<ImageType>(10, 0);
  ImageType::RegionType region(image->GetLargestPossibleRegion());

  otb::MaskedIteratorDecorator<itk::ImageRegionIterator<ImageType> > it(mask, image, region);
  return EXIT_SUCCESS;
}

// ---------------------- Initialization code ----------------------------------
template <typename IteratorType>
void
InitializeIterator(IteratorType&, typename IteratorType::RegionType)
{
  // by default : nothing to do
}

// specialization for otb::SubsampledImageRegionIterator<otb::Image<double, 2> >
template <>
void
InitializeIterator< otb::SubsampledImageRegionIterator< otb::Image<double, 2> > >(
  otb::SubsampledImageRegionIterator< otb::Image<double, 2> >& it,
  otb::SubsampledImageRegionIterator<otb::Image<double, 2> >::RegionType)
{
  it.SetSubsampleFactor(2);
}

// -------------------------- ForwardTest --------------------------------------
// Function to test the forward iteration interface
template <typename IteratorType, typename MaskIteratorType>
int ForwardTest(typename MaskIteratorType::ImageType::Pointer mask, typename IteratorType::ImageType::Pointer image, typename IteratorType::ImageType::RegionType region)
{
  otb::MaskedIteratorDecorator<IteratorType,MaskIteratorType> it(mask, image, region);

  // specific initialization code
  InitializeIterator<IteratorType>(it.GetImageIterator(),region);
  if (it.HasMask())
    {
    InitializeIterator<MaskIteratorType>(it.GetMaskIterator(),region);
    }

  it.GoToBegin();
  if (!it.IsAtBegin()) {return 1;}

  unsigned int loopCount = 0;
  for(; !it.IsAtEnd(); ++it)
  {
    if (loopCount != 0 && it.IsAtBegin()) {return 2;}
    if (it.IsAtEnd()) {return 3;}

    //it.Set(it.Value() * 0.42);

    loopCount += 1;
  }

  if(!it.IsAtEnd()) {return 4;}
  return 0;
}

// -------------------------- ReverseTest --------------------------------------
// Test reverse iteration interface
template <typename IteratorType, typename MaskIteratorType>
int ReverseTest(typename MaskIteratorType::ImageType::Pointer mask, typename IteratorType::ImageType::Pointer image, typename IteratorType::ImageType::RegionType region)
{
  otb::MaskedIteratorDecorator<IteratorType,MaskIteratorType> it(mask, image, region);

  // specific initialization code
  InitializeIterator<IteratorType>(it.GetImageIterator(),region);
  if (it.HasMask())
    {
    InitializeIterator<MaskIteratorType>(it.GetMaskIterator(),region);
    }

  it.GoToEnd();
  if (!it.IsAtEnd()) {return 1;}

  bool beginReached = false;
  while (!it.IsAtBegin())
    {
    --it;
    if (it.IsAtEnd()) {return 2;}
    if (beginReached)
      {
      return 3;
      }
    if (it.IsAtBegin())
      {
      beginReached = true;
      }
    }

  if(!it.IsAtBegin()) {return 4;}
  return 0;
}

// -------------------------- BijectiveTest --------------------------------------
// Check bijection between iterated and non masked
// i.e all locations where mask value != 0 are in the iteration (injection)
// and mask value != 0 at all iteration locations (surjection)
// Templated to test decoration of different iterator types
template <typename IteratorType, typename MaskIteratorType>
int BijectiveTest(typename MaskIteratorType::ImageType::Pointer mask, typename IteratorType::ImageType::Pointer image, typename IteratorType::ImageType::RegionType region)
{
  otb::MaskedIteratorDecorator<IteratorType,MaskIteratorType> itDecorated(mask, image, region);
  IteratorType it(image, region);

  // specific initialization code
  InitializeIterator<IteratorType>(itDecorated.GetImageIterator(),region);
  InitializeIterator<IteratorType>(it,region);
  if (itDecorated.HasMask())
    {
    InitializeIterator<MaskIteratorType>(itDecorated.GetMaskIterator(),region);
    }

  it.GoToBegin();
  itDecorated.GoToBegin();

  // Find the non maked begin for the image iterator
  if (itDecorated.HasMask())
    {
    while (mask->GetPixel(it.GetIndex()) == 0 && !it.IsAtEnd())
      {
      ++it;
      }
    }

  // Begins are the same
  if (!(it.GetIndex() == itDecorated.GetIndex()
     && it.GetIndex() == itDecorated.GetImageIterator().GetIndex()))
  {
    return 1;
  }

  if (itDecorated.HasMask() && it.GetIndex() != itDecorated.GetMaskIterator().GetIndex())
    {
    return 1;
    }

  // Advance both and check
  while (!it.IsAtEnd() && !itDecorated.IsAtEnd())
  {
    // Iteration locations are the same
    if (!(it.GetIndex() == itDecorated.GetIndex()
       && it.GetIndex() == itDecorated.GetImageIterator().GetIndex()))
      {
      return 2;
      }
    if (itDecorated.HasMask() && it.GetIndex() != itDecorated.GetMaskIterator().GetIndex())
      {
      return 2;
      }

    ++itDecorated;
    if (itDecorated.HasMask())
      {
      do
        {
        ++it;
        } while (mask->GetPixel(it.GetIndex()) == 0 && !it.IsAtEnd());
      }
    else
      {
      ++it;
      }
  }

  // Check IsAtEnd
  if (!(it.IsAtEnd() && itDecorated.IsAtEnd()))
  {
    return 3;
  }

  return 0;
}

// Multiplex to forward, reverse and bijection test
template <typename IteratorType, typename MaskIteratorType>
int TripleTest(typename IteratorType::ImageType::Pointer image,typename MaskIteratorType::ImageType::Pointer mask, typename IteratorType::ImageType::RegionType region)
{
  int ret;
  int retGlobal = EXIT_SUCCESS;

  ret = ForwardTest<IteratorType,MaskIteratorType>(mask, image, region);
  if (ret>0)
    {
    std::cout << "Forward(FAILED:"<<ret<<") ";
    retGlobal = EXIT_FAILURE;
    }

  ret = ReverseTest<IteratorType,MaskIteratorType>(mask, image, region);
  if (ret>0)
    {
    std::cout << "Reverse(FAILED:"<<ret<<") ";
    retGlobal = EXIT_FAILURE;
    }

  ret = BijectiveTest<IteratorType,MaskIteratorType>(mask, image, region);
  if (ret>0)
    {
    std::cout << "Bijective(FAILED:"<<ret<<") ";
    retGlobal = EXIT_FAILURE;
    }

  if (retGlobal == EXIT_SUCCESS)
    {
    std::cout << "PASSED";
    }
  return retGlobal;
}

// -------------------------- Nominal case -------------------------------------
int otbMaskedIteratorDecoratorNominal(int itkNotUsed(argc), char * itkNotUsed(argv) [])
{
  typedef otb::Image<double, 2> ImageType;
  ImageType::Pointer image = GetTestImage<ImageType>(10, 10);
  ImageType::Pointer mask = GetTestImage<ImageType>(10, 0);
  ImageType::RegionType region(image->GetLargestPossibleRegion());
  FillHalf<ImageType>(mask, region, 1);
  int ret;
  int retGlobal = EXIT_SUCCESS;

  std::cout << std::endl << "itk::ImageRegionIterator : ";
  ret = TripleTest< itk::ImageRegionIterator<ImageType>,
                    itk::ImageRegionIterator<ImageType> >(image, mask, region);
  retGlobal = (ret == EXIT_FAILURE ? EXIT_FAILURE : retGlobal);

  std::cout << std::endl << "itk::ImageRegionConstIterator : ";
  ret = TripleTest< itk::ImageRegionConstIterator<ImageType>,
                    itk::ImageRegionConstIterator<ImageType> >(image, mask, region);
  retGlobal = (ret == EXIT_FAILURE ? EXIT_FAILURE : retGlobal);

  // std::cout << std::endl << "otb::SubsampledImageRegionIterator : ";
  // ret = TripleTest< otb::SubsampledImageRegionIterator<ImageType>,
  //                   otb::SubsampledImageRegionIterator<ImageType> >(image, mask, region);
  // retGlobal = (ret == EXIT_FAILURE ? EXIT_FAILURE : retGlobal);

  return retGlobal;
}

// ------------------------ Degenerate cases -----------------------------------
int otbMaskedIteratorDecoratorDegenerate(int itkNotUsed(argc), char * itkNotUsed(argv) [])
{
  // Fully masked (0 everywhere)
  typedef otb::Image<double, 2> ImageType;
  ImageType::Pointer image = GetTestImage<ImageType>(10, 10);
  ImageType::Pointer mask = GetTestImage<ImageType>(10, 0);
  ImageType::RegionType region(image->GetLargestPossibleRegion());

  return TripleTest<itk::ImageRegionIterator<ImageType>,
                    itk::ImageRegionIterator<ImageType> >(image, mask, region);
}

// --------------------------- Extended cases ----------------------------------
int otbMaskedIteratorDecoratorExtended(int itkNotUsed(argc), char * itkNotUsed(argv) [])
{
  typedef otb::VectorImage<double, 2> ImageType;
  typedef otb::Image<unsigned char, 2> MaskType;
  otb::VectorImage<double, 2>::PixelType pixel(3);
  pixel.Fill(12);
  ImageType::Pointer image = GetTestImage<ImageType>(10,pixel ,3);
  MaskType::Pointer mask = GetTestImage<MaskType>(10, 0);
  ImageType::RegionType region(image->GetLargestPossibleRegion());
  FillHalf<MaskType>(mask, region, 1);
  int ret;
  int retGlobal = EXIT_SUCCESS;

  std::cout << std::endl << "itk::ImageRegionIterator : ";
  ret = TripleTest< itk::ImageRegionIterator<ImageType>,
                    itk::ImageRegionIterator<MaskType> >(image, mask, region);
  retGlobal = (ret == EXIT_FAILURE ? EXIT_FAILURE : retGlobal);

  std::cout << std::endl << "itk::ImageRegionConstIterator : ";
  ret = TripleTest< itk::ImageRegionConstIterator<ImageType>,
                    itk::ImageRegionConstIterator<MaskType> >(image, mask, region);
  retGlobal = (ret == EXIT_FAILURE ? EXIT_FAILURE : retGlobal);

  std::cout << std::endl << "itk::ImageRegionIterator without mask: ";
  ret = TripleTest< itk::ImageRegionIterator<ImageType>,
                    itk::ImageRegionIterator<MaskType> >(image, NULL, region);
  retGlobal = (ret == EXIT_FAILURE ? EXIT_FAILURE : retGlobal);

  std::cout << std::endl << "itk::ImageRegionConstIterator without mask: ";
  ret = TripleTest< itk::ImageRegionConstIterator<ImageType>,
                    itk::ImageRegionConstIterator<MaskType> >(image, NULL, region);
  retGlobal = (ret == EXIT_FAILURE ? EXIT_FAILURE : retGlobal);

  return retGlobal;
}

/* Other iterators potentially compatible:

Different constructor arguments than (image, region)
itk::PathIterator
itk::LineIterator
itk::SliceIterator
itk::NeighborhoodIterator

Needs initialization code:
itk::ImageRandomConstIteratorWithIndex
itk::ImageRandomIteratorWithIndex
itk::ImageRandomNonRepeatingConstIteratorWithIndex
itk::ImageRandomNonRepeatingIteratorWithIndex

otb::SubsampledImageRegionIterator  : GoToEnd is buggy !

Different iteration interface than normal iterators:
itk::ImageScanlineIterator
itk::ImageScanlineConstIterator

GoToEnd is not implemented
itk::ImageLinearIteratorWithIndex
itk::ReflectiveImageRegionIterator
itk::ImageRegionExclusionConstIteratorWithIndex
itk::ImageRegionIteratorWithIndex

Other problem:
itk::ImageRegionReverseIterator>() // IsAtEnd not a const method
otb::PolyLineImageIterator>() // header not found
itk::ImageRandomConstIteratorWithOnlyIndex>() // no Value method
*/
<|endoftext|>


<commit_before><commit_msg>re-enable OpenCL on Apple for development<commit_after><|endoftext|>


<commit_before>/*=========================================================================

  Program:   ORFEO Toolbox
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) Centre National d'Etudes Spatiales. All rights reserved.
  See OTBCopyright.txt for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notices for more information.

=========================================================================*/
#include <set>
#include "otbImage.h"

#include "itkImageRegionIterator.h"
#include "itkImageRegionReverseIterator.h"
#include "itkImageRandomIteratorWithIndex.h"
#include "itkImageScanlineIterator.h"
#include "otbSubsampledImageRegionIterator.h"

#include "otbMaskedIteratorDecorator.h"

// Generate a test image of specified size and value
template <typename ImageType>
typename ImageType::Pointer GetTestImage(itk::SizeValueType fillSize, const typename ImageType::PixelType& value)
{
  typename ImageType::Pointer image = ImageType::New();
  typename ImageType::SizeType size;
  size.Fill(fillSize);

  typename ImageType::RegionType region;
  region.SetSize(size);

  image->SetRegions(region);
  image->Allocate();
  image->FillBuffer(value);
  return image;
}

// Fill half of the pixels with a value
// Used for generating a test mask
template <typename ImageType>
void FillHalf(typename ImageType::Pointer image, const typename ImageType::RegionType& region, const typename ImageType::PixelType& value)
{
  itk::ImageRegionIterator<ImageType> it(image, region);
  unsigned int count = 0;
  for(it.GoToBegin(); !it.IsAtEnd(); ++it, ++count)
  {
    if (count % 2 == 0)
    {
      it.Set(value);
    }
  }
}

// Test template instanciation
int otbMaskedIteratorDecoratorNew(int itkNotUsed(argc), char * itkNotUsed(argv) [])
{
  typedef otb::Image<double, 2> ImageType;
  ImageType::Pointer image = GetTestImage<ImageType>(10, 10);
  ImageType::Pointer mask = GetTestImage<ImageType>(10, 0);
  ImageType::RegionType region(image->GetLargestPossibleRegion());

  otb::MaskedIteratorDecorator<itk::ImageRegionIterator<ImageType> > it(mask, image, region);
  return EXIT_SUCCESS;
}

// Test forward iteration interface
int otbMaskedIteratorDecoratorForward(int itkNotUsed(argc), char * itkNotUsed(argv) [])
{
  typedef otb::Image<double, 2> ImageType;
  ImageType::Pointer image = GetTestImage<ImageType>(10, 10);
  ImageType::Pointer mask = GetTestImage<ImageType>(10, 0);
  ImageType::RegionType region(image->GetLargestPossibleRegion());
  FillHalf<ImageType>(mask, region, 1);

  otb::MaskedIteratorDecorator<itk::ImageRegionIterator<ImageType> > it(mask, image, region);

  it.GoToBegin();
  if (!it.IsAtBegin()) {return EXIT_FAILURE;}

  unsigned int loopCount = 0;
  for(; !it.IsAtEnd(); ++it)
  {
    if (loopCount != 0 && it.IsAtBegin()) {return EXIT_FAILURE;}
    if (it.IsAtEnd()) {return EXIT_FAILURE;}

    it.Set(it.Value() * 0.42);

    loopCount += 1;
  }

  if(!it.IsAtEnd()) {return EXIT_FAILURE;}
  return EXIT_SUCCESS;
}

// Test reverse iteration interface
int otbMaskedIteratorDecoratorReverse(int itkNotUsed(argc), char * itkNotUsed(argv) [])
{
  typedef otb::Image<double, 2> ImageType;
  ImageType::Pointer image = GetTestImage<ImageType>(10, 10);
  ImageType::Pointer mask = GetTestImage<ImageType>(10, 0);
  ImageType::RegionType region(image->GetLargestPossibleRegion());
  FillHalf<ImageType>(mask, region, 1);

  otb::MaskedIteratorDecorator<itk::ImageRegionIterator<ImageType> > it(mask, image, region);

  it.GoToEnd();
  if (!it.IsAtEnd()) {return EXIT_FAILURE;}

  bool beginReached = false;
  do
  {
    --it;

    if (it.IsAtEnd()) {return EXIT_FAILURE;}
    if (it.IsAtBegin())
    {
      if (beginReached)
      {
        return EXIT_FAILURE;
      }
      else {
        beginReached = true;
      }
    }

    it.Set(it.Value() * 0.42);
  } while (!it.IsAtBegin());

  if(!it.IsAtBegin()) {return EXIT_FAILURE;}
  return EXIT_SUCCESS;
}

// Check bijection between iterated and non masked
// i.e all locations where mask value != 0 are in the iteration (injection)
// and mask value != 0 at all iteration locations (surjection)
// Templated to test decoration of different iterator types
template <typename ImageType, template <typename ImageType> typename IteratorType>
int BijectiveTest()
{
  typename ImageType::Pointer image = GetTestImage<ImageType>(10, 10);
  typename ImageType::Pointer mask = GetTestImage<ImageType>(10, 0);
  typename ImageType::RegionType region(image->GetLargestPossibleRegion());
  FillHalf<ImageType>(mask, region, 1);

  otb::MaskedIteratorDecorator<IteratorType<ImageType> > itDecorated(mask, image, region);
  IteratorType<ImageType> it(image, region);

  it.GoToBegin();
  itDecorated.GoToBegin();
  while (!it.IsAtEnd() && itDecorated.IsAtEnd())
  {
    // Iteration locations are the same
    if (it.GetIndex() != itDecorated.GetIndex()) {return EXIT_FAILURE;}

    ++itDecorated;
    do
    {
      ++it;
    } while (mask->GetPixel(it.GetIndex()) == 0 && !it.IsAtEnd());
  }
  return EXIT_SUCCESS;
}

int otbMaskedIteratorDecoratorBijective(int itkNotUsed(argc), char * itkNotUsed(argv) [])
{
  typedef otb::Image<double, 2> ImageType;
  return BijectiveTest<ImageType, itk::ImageRegionIterator>()
      && BijectiveTest<ImageType, itk::ImageRegionConstIterator>()
      && BijectiveTest<ImageType, itk::ImageRandomConstIteratorWithIndex>()
      //&& BijectiveTest<ImageType, itk::ImageRegionReverseIterator>() // IsAtEnd not a const method
      //&& BijectiveTest<ImageType, itk::ImageLinearIteratorWithIndex>(); // does not implement GoToEnd
      //&& BijectiveTest<ImageType, otb::PolyLineImageIterator>() // header not found
      && BijectiveTest<ImageType, otb::SubsampledImageRegionIterator>()
      //&& BijectiveTest<ImageType, itk::PathIterator>() // different template interface, testable but not with BijectiveTest
      //&& BijectiveTest<ImageType, itk::ConditionalConstIterator>() // abstract class
      //&& BijectiveTest<ImageType, itk::ReflectiveImageRegionIterator>() // GoToEnd not implemented
      && BijectiveTest<ImageType, itk::ImageRandomIteratorWithIndex>()
      //&& BijectiveTest<ImageType, itk::NeighborhoodIterator>() // different template interface, testable but not with BijectiveTest
      && BijectiveTest<ImageType, itk::ImageScanlineIterator>()
      //&& BijectiveTest<ImageType, itk::DataObjectIterator>() // different template interface, testable but not with BijectiveTest
      ;
}

/*
itkQuadEdgeMeshFrontIterator.h
itkQuadEdgeMeshBaseIterator.h
itkLineIterator.h
itkShapedFloodFilledImageFunctionConditionalConstIterator.h
itkImageConstIteratorWithOnlyIndex.h
itkCorrespondenceDataStructureIterator.h
itkChildTreeIterator.h
itkImageSliceConstIteratorWithIndex.h
itkImageRegionConstIterator.h
itkLevelOrderTreeIterator.h
itkSliceIterator.h
itkImageRegionConstIteratorWithIndex.h
itkConstSliceIterator.h
itkImageRandomNonRepeatingConstIteratorWithIndex.h
itkTreeIteratorClone.h
itkImageLinearIteratorWithIndex.h
itkImageRandomConstIteratorWithOnlyIndex.h
itkShapedFloodFilledFunctionConditionalConstIterator.h
itkFloodFilledImageFunctionConditionalConstIterator.h
itkFloodFilledImageFunctionConditionalIterator.h
itkImageRegionIteratorWithIndex.h
itkImageRandomNonRepeatingIteratorWithIndex.h
itkImageRegionExclusionIteratorWithIndex.h
itkImageRegionConstIteratorWithOnlyIndex.h
itkFloodFilledSpatialFunctionConditionalIterator.h
itkTreeIteratorBase.h
itkImageScanlineIterator.h
itkPreOrderTreeIterator.h
itkFloodFilledSpatialFunctionConditionalConstIterator.h
itkThreadedIteratorRangePartitioner.h
itkImageSliceIteratorWithIndex.h
itkImageConstIteratorWithIndex.h
itkLineConstIterator.h
itkShapedFloodFilledImageFunctionConditionalIterator.h
itkInOrderTreeIterator.h
itkConditionalConstIterator.h
itkConstNeighborhoodIteratorWithOnlyIndex.h
itkImageRegionExclusionConstIteratorWithIndex.h
itkFloodFilledFunctionConditionalConstIterator.h
itkRootTreeIterator.h
itkImageIteratorWithIndex.h
itkPostOrderTreeIterator.h
itkImageLinearConstIteratorWithIndex.h
itkLeafTreeIterator.h
itkImageScanlineConstIterator.h

otbRCC8VertexIterator.txx
otbRCC8EdgeIterator.h
otbRCC8InEdgeIterator.txx
otbRCC8EdgeIterator.txx
otbRCC8OutEdgeIterator.txx
otbRCC8OutEdgeIterator.h
otbRCC8VertexIterator.h
otbRCC8InEdgeIterator.h
*/
<commit_msg>ENH: Improve MaskedIteratorDecorator test<commit_after>/*=========================================================================

  Program:   ORFEO Toolbox
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) Centre National d'Etudes Spatiales. All rights reserved.
  See OTBCopyright.txt for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notices for more information.

=========================================================================*/
#include <set>
#include "otbImage.h"

#include "itkImageRegionIterator.h"
#include "itkImageRegionReverseIterator.h"
#include "itkImageRandomIteratorWithIndex.h"
#include "itkImageScanlineIterator.h"
#include "itkImageRandomNonRepeatingIteratorWithIndex.h"
#include "otbSubsampledImageRegionIterator.h"

#include "otbMaskedIteratorDecorator.h"

// Generate a test image of specified size and value
template <typename ImageType>
typename ImageType::Pointer GetTestImage(itk::SizeValueType fillSize, const typename ImageType::PixelType& value)
{
  typename ImageType::Pointer image = ImageType::New();
  typename ImageType::SizeType size;
  size.Fill(fillSize);

  typename ImageType::RegionType region;
  region.SetSize(size);

  image->SetRegions(region);
  image->Allocate();
  image->FillBuffer(value);
  return image;
}

// Fill half of the pixels with a value
// Used for generating a test mask
template <typename ImageType>
void FillHalf(typename ImageType::Pointer image, const typename ImageType::RegionType& region, const typename ImageType::PixelType& value)
{
  itk::ImageRegionIterator<ImageType> it(image, region);
  unsigned int count = 0;
  for(it.GoToBegin(); !it.IsAtEnd(); ++it, ++count)
  {
    if (count % 2 == 0)
    {
      it.Set(value);
    }
  }
}

// Test template instanciation
int otbMaskedIteratorDecoratorNew(int itkNotUsed(argc), char * itkNotUsed(argv) [])
{
  typedef otb::Image<double, 2> ImageType;
  ImageType::Pointer image = GetTestImage<ImageType>(10, 10);
  ImageType::Pointer mask = GetTestImage<ImageType>(10, 0);
  ImageType::RegionType region(image->GetLargestPossibleRegion());

  otb::MaskedIteratorDecorator<itk::ImageRegionIterator<ImageType> > it(mask, image, region);
  return EXIT_SUCCESS;
}

// Test forward iteration interface
int otbMaskedIteratorDecoratorForward(int itkNotUsed(argc), char * itkNotUsed(argv) [])
{
  typedef otb::Image<double, 2> ImageType;
  ImageType::Pointer image = GetTestImage<ImageType>(10, 10);
  ImageType::Pointer mask = GetTestImage<ImageType>(10, 0);
  ImageType::RegionType region(image->GetLargestPossibleRegion());
  FillHalf<ImageType>(mask, region, 1);

  otb::MaskedIteratorDecorator<itk::ImageRegionIterator<ImageType> > it(mask, image, region);

  it.GoToBegin();
  if (!it.IsAtBegin()) {return EXIT_FAILURE;}

  unsigned int loopCount = 0;
  for(; !it.IsAtEnd(); ++it)
  {
    if (loopCount != 0 && it.IsAtBegin()) {return EXIT_FAILURE;}
    if (it.IsAtEnd()) {return EXIT_FAILURE;}

    it.Set(it.Value() * 0.42);

    loopCount += 1;
  }

  if(!it.IsAtEnd()) {return EXIT_FAILURE;}
  return EXIT_SUCCESS;
}

// Test reverse iteration interface
int otbMaskedIteratorDecoratorReverse(int itkNotUsed(argc), char * itkNotUsed(argv) [])
{
  typedef otb::Image<double, 2> ImageType;
  ImageType::Pointer image = GetTestImage<ImageType>(10, 10);
  ImageType::Pointer mask = GetTestImage<ImageType>(10, 0);
  ImageType::RegionType region(image->GetLargestPossibleRegion());
  FillHalf<ImageType>(mask, region, 1);

  otb::MaskedIteratorDecorator<itk::ImageRegionIterator<ImageType> > it(mask, image, region);

  it.GoToEnd();
  if (!it.IsAtEnd()) {return EXIT_FAILURE;}

  bool beginReached = false;
  do
  {
    --it;

    if (it.IsAtEnd()) {return EXIT_FAILURE;}
    if (it.IsAtBegin())
    {
      if (beginReached)
      {
        return EXIT_FAILURE;
      }
      else {
        beginReached = true;
      }
    }

    it.Set(it.Value() * 0.42);
  } while (!it.IsAtBegin());

  if(!it.IsAtBegin()) {return EXIT_FAILURE;}
  return EXIT_SUCCESS;
}

// Check bijection between iterated and non masked
// i.e all locations where mask value != 0 are in the iteration (injection)
// and mask value != 0 at all iteration locations (surjection)
// Templated to test decoration of different iterator types
template <typename ImageType, template <typename ImageType> typename IteratorType>
int BijectiveTest()
{
  typename ImageType::Pointer image = GetTestImage<ImageType>(10, 10);
  typename ImageType::Pointer mask = GetTestImage<ImageType>(10, 0);
  typename ImageType::RegionType region(image->GetLargestPossibleRegion());
  FillHalf<ImageType>(mask, region, 1);

  otb::MaskedIteratorDecorator<IteratorType<ImageType> > itDecorated(mask, image, region);
  IteratorType<ImageType> it(image, region);

  it.GoToBegin();
  itDecorated.GoToBegin();
  while (!it.IsAtEnd() && itDecorated.IsAtEnd())
  {
    // Iteration locations are the same
    if (it.GetIndex() != itDecorated.GetIndex()) {return EXIT_FAILURE;}

    ++itDecorated;
    do
    {
      ++it;
    } while (mask->GetPixel(it.GetIndex()) == 0 && !it.IsAtEnd());
  }
  return EXIT_SUCCESS;
}

int otbMaskedIteratorDecoratorBijective(int itkNotUsed(argc), char * itkNotUsed(argv) [])
{
  typedef otb::Image<double, 2> ImageType;
  return BijectiveTest<ImageType, itk::ImageRegionIterator>()
      && BijectiveTest<ImageType, itk::ImageRegionConstIterator>()
      && BijectiveTest<ImageType, itk::ImageRandomConstIteratorWithIndex>()
      && BijectiveTest<ImageType, otb::SubsampledImageRegionIterator>()
      && BijectiveTest<ImageType, itk::ImageRandomIteratorWithIndex>()
      && BijectiveTest<ImageType, itk::ImageScanlineIterator>()
      && BijectiveTest<ImageType, itk::ImageScanlineConstIterator>()
      && BijectiveTest<ImageType, itk::ImageRandomNonRepeatingConstIteratorWithIndex>()
      && BijectiveTest<ImageType, itk::ImageRandomNonRepeatingIteratorWithIndex>()
      ;

      // Other iterators potentially compatible:

      // Different template interface, testable but not with BijectiveTest:
      // itk::PathIterator
      // itk::NeighborhoodIterator
      // itk::DataObjectIterator

      // Different constructor, testable but not with BijectiveTest
      // itk::LineIterator
      // itk::SliceIterator

      // GoToEnd is not implemented
      // itk::ImageLinearIteratorWithIndex
      // itk::ReflectiveImageRegionIterator
      // itk::ImageRegionExclusionConstIteratorWithIndex
      // itk::ImageRegionIteratorWithIndex

      // Other problem:
      // itk::ImageRegionReverseIterator>() // IsAtEnd not a const method
      // otb::PolyLineImageIterator>() // header not found
      // itk::ImageRandomConstIteratorWithOnlyIndex>() // no Value method

}
<|endoftext|>


<commit_before>// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.

#include <vespa/memfilepersistence/device/mountpointlist.h>
#include <vespa/vespalib/io/fileutil.h>
#include <vespa/storageframework/defaultimplementation/clock/fakeclock.h>
#include <vespa/vdstestlib/cppunit/macros.h>

using vespalib::fileExists;
using vespalib::isDirectory;
using vespalib::isSymLink;
using vespalib::readLink;

namespace storage {

namespace memfile {

class MountPointList_Test : public CppUnit::TestFixture {
    CPPUNIT_TEST_SUITE(MountPointList_Test);
    CPPUNIT_TEST(testScanning);
    CPPUNIT_TEST(testStatusFile);
    CPPUNIT_TEST(testInitDisks);
    CPPUNIT_TEST_SUITE_END();

    static const std::string _prefix;

public:
    void testScanning();
    void testStatusFile();
    void testInitDisks();

    void init();
    void tearDown() override;

    framework::defaultimplementation::FakeClock _clock;

private:
    DeviceManager::UP newDeviceManager() {
        return DeviceManager::UP(
                new DeviceManager(
                        DeviceMapper::UP(new SimpleDeviceMapper),
                        _clock));
    }
};

CPPUNIT_TEST_SUITE_REGISTRATION(MountPointList_Test);

const std::string MountPointList_Test::_prefix("./vdsroot");

namespace {
    void run(const std::string& cmd) {
        CPPUNIT_ASSERT_MESSAGE(cmd, system(cmd.c_str()) == 0);
    }
}

void MountPointList_Test::init()
{
    tearDown();
    run("rm -rf "+_prefix);
    run("mkdir -p "+_prefix+"/disks");

    run("mkdir "+_prefix+"/disks/d0");    // Regular dir
    run("mkdir "+_prefix+"/disks/d1");    // Inaccessible dir
    run("chmod 000 "+_prefix+"/disks/d1");
    run("mkdir "+_prefix+"/disks/D2");    // Wrongly named dir
    run("mkdir "+_prefix+"/disks/d3");    // Regular non-empty dir
    run("touch "+_prefix+"/disks/d3/foo");
    run("touch "+_prefix+"/disks/d4");    // Not a dir
    run("ln -s D2 "+_prefix+"/disks/d5"); // Symlink to dir
    run("ln -s d4 "+_prefix+"/disks/d6"); // Symlink to file
}

void MountPointList_Test::tearDown()
{
    try{
        if (fileExists(_prefix+"/disks/d1")) {
            run("chmod 755 "+_prefix+"/disks/d1");
        }
    } catch (std::exception& e) {
        std::cerr << "Failed to clean up: " << e.what() << "\n";
    }
}

void MountPointList_Test::testScanning()
{
    init();
    MountPointList list(_prefix,
                        std::vector<vespalib::string>(),
                        DeviceManager::UP(
                                new DeviceManager(
                                        DeviceMapper::UP(new SimpleDeviceMapper),
                                        _clock)));
    list.scanForDisks();

        // Check that we got the expected entries.
    CPPUNIT_ASSERT_EQUAL(7u, list.getSize());

    for (uint32_t i=0; i<7u; ++i) {
        std::ostringstream ost;
        ost << _prefix << "/disks/d" << i;
        CPPUNIT_ASSERT_EQUAL(ost.str(), list[i].getPath());
    }

    // Note.. scanForDisks() should not in any circumstances access the
    // disks. Thus it should not know that d1 is inaccessible, or that d6
    // is actually a symlink to a file
    CPPUNIT_ASSERT_EQUAL(Device::OK,           list[0].getState());
    CPPUNIT_ASSERT_EQUAL(Device::OK,           list[1].getState());
    CPPUNIT_ASSERT_EQUAL(Device::NOT_FOUND,    list[2].getState());
    CPPUNIT_ASSERT_EQUAL(Device::OK,           list[3].getState());
    CPPUNIT_ASSERT_EQUAL(Device::PATH_FAILURE, list[4].getState());
    CPPUNIT_ASSERT_EQUAL(Device::OK,           list[5].getState());
    CPPUNIT_ASSERT_EQUAL(Device::OK,           list[6].getState());

    list.verifyHealthyDisks(-1);
    CPPUNIT_ASSERT_EQUAL(Device::OK,               list[0].getState());
    CPPUNIT_ASSERT_EQUAL(Device::NO_PERMISSION,    list[1].getState());
    CPPUNIT_ASSERT_EQUAL(Device::NOT_FOUND,        list[2].getState());
    CPPUNIT_ASSERT_EQUAL(Device::INTERNAL_FAILURE, list[3].getState());
    CPPUNIT_ASSERT_EQUAL(Device::PATH_FAILURE,     list[4].getState());
    CPPUNIT_ASSERT_EQUAL(Device::OK,               list[5].getState());
    CPPUNIT_ASSERT_EQUAL(Device::PATH_FAILURE,     list[6].getState());
}

void MountPointList_Test::testStatusFile()
{
    init();
    std::string statusFileName(_prefix + "/disks.status");

    // Try reading non-existing file, and writing a file
    {
        MountPointList list(_prefix,
                            std::vector<vespalib::string>(),
                            DeviceManager::UP(
                                    new DeviceManager(
                                            DeviceMapper::UP(new SimpleDeviceMapper),
                                            _clock)));

        _clock.setAbsoluteTimeInSeconds(5678);
        list.scanForDisks();

        // File does not currently exist, that should be ok though.
        list.readFromFile();
        list.verifyHealthyDisks(-1);
        CPPUNIT_ASSERT_EQUAL(7u, list.getSize());
        list[5].addEvent(IOEvent(1234, Device::IO_FAILURE, "Argh", "Hmm"));
        CPPUNIT_ASSERT_EQUAL(Device::IO_FAILURE, list[5].getState());

        // Write to file.
        list.writeToFile();
    }

    // Check contents of file.
    {
        std::ifstream in(statusFileName.c_str());
        std::string line;
        CPPUNIT_ASSERT(std::getline(in, line));

        CPPUNIT_ASSERT_PREFIX(
                std::string(_prefix + "/disks/d1 3 5678 IoException: NO PERMISSION: "
                            "open(./vdsroot/disks/d1/chunkinfo, 0x1): Failed, "
                            "errno(13): Permission denied"),
                line);
        CPPUNIT_ASSERT(std::getline(in, line));
        CPPUNIT_ASSERT_PREFIX(
                std::string(_prefix +"/disks/d2 1 5678 Disk not found during scanning of "
                            "disks directory"),
                line);
        CPPUNIT_ASSERT(std::getline(in, line));
        CPPUNIT_ASSERT_PREFIX(
                std::string(_prefix + "/disks/d3 4 5678 Foreign data in mountpoint. New "
                            "mountpoints added should be empty."),
                line);
        CPPUNIT_ASSERT(std::getline(in, line));
        CPPUNIT_ASSERT_PREFIX(
                std::string(_prefix + "/disks/d4 2 5678 File d4 in disks directory is not "
                            "a directory."),
                line);
        CPPUNIT_ASSERT(std::getline(in, line));
        CPPUNIT_ASSERT_PREFIX(std::string(_prefix + "/disks/d5 5 1234 Argh"),
                              line);
        CPPUNIT_ASSERT(std::getline(in, line));
        CPPUNIT_ASSERT_PREFIX(
                std::string(_prefix + "/disks/d6 2 5678 The path exist, but is not a "
                            "directory."),
                line);
        CPPUNIT_ASSERT(std::getline(in, line));
        CPPUNIT_ASSERT_EQUAL(std::string("EOF"), line);
    }

    // Starting over to get new device instances.
    // Scan disk, read file, and check that erronious disks are not used.
    {
        MountPointList list(_prefix,
                            std::vector<vespalib::string>(),
                            DeviceManager::UP(
                                    new DeviceManager(
                                            DeviceMapper::UP(new SimpleDeviceMapper),
                                            _clock)));
        list.scanForDisks();
        list.readFromFile();
            // Check that we got the expected entries.
        CPPUNIT_ASSERT_EQUAL(7u, list.getSize());

        // Note.. scanForDisks() should not under any circumstance access the
        // disks. Thus it should not know that d1 is inaccessible.
        CPPUNIT_ASSERT_EQUAL(Device::OK,            list[0].getState());
        CPPUNIT_ASSERT_EQUAL(Device::NO_PERMISSION, list[1].getState());
        CPPUNIT_ASSERT_EQUAL(Device::NOT_FOUND,     list[2].getState());
        CPPUNIT_ASSERT_EQUAL(Device::INTERNAL_FAILURE, list[3].getState());
        CPPUNIT_ASSERT_EQUAL(Device::PATH_FAILURE,  list[4].getState());
        CPPUNIT_ASSERT_EQUAL(Device::IO_FAILURE,    list[5].getState());
        CPPUNIT_ASSERT_EQUAL(Device::PATH_FAILURE,  list[6].getState());
    }
}

void MountPointList_Test::testInitDisks()
{
    vespalib::string d3target = "d3target";
    vespalib::string foodev = _prefix + "/foodev";
    vespalib::string bardev = _prefix + "/bardev";

    tearDown();
    run("rm -rf " + _prefix);
    run("mkdir -p " + _prefix + "/disks/d2");
    run("ln -s " + d3target + " " + _prefix + "/disks/d3");

    std::vector<vespalib::string> diskPaths {
        // disks/d0 should become a regular directory
        _prefix + "/disks/d0",
        // disks/d1 should be a symlink to /foo
        foodev,
        // disks/d2 should already be a directory
        "/ignored",
        // disks/d3 should already be a symlink
        "/ignored2"
    };

    MountPointList list(_prefix, diskPaths, newDeviceManager());
    list.initDisks();

    CPPUNIT_ASSERT(isDirectory(_prefix + "/disks"));
    CPPUNIT_ASSERT(isDirectory(_prefix + "/disks/d0"));
    CPPUNIT_ASSERT(isSymLink(_prefix + "/disks/d1"));
    CPPUNIT_ASSERT_EQUAL(foodev, readLink(_prefix + "/disks/d1"));
    CPPUNIT_ASSERT(isDirectory(_prefix + "/disks/d2"));
    CPPUNIT_ASSERT(isSymLink(_prefix + "/disks/d3"));
    CPPUNIT_ASSERT_EQUAL(d3target, readLink(_prefix + "/disks/d3"));
}

} // memfile

} // storage
<commit_msg>Enable test to run as root<commit_after>// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.

#include <vespa/memfilepersistence/device/mountpointlist.h>
#include <vespa/vespalib/io/fileutil.h>
#include <vespa/storageframework/defaultimplementation/clock/fakeclock.h>
#include <vespa/vdstestlib/cppunit/macros.h>

using vespalib::fileExists;
using vespalib::isDirectory;
using vespalib::isSymLink;
using vespalib::readLink;

namespace storage {

namespace memfile {

class MountPointList_Test : public CppUnit::TestFixture {
    CPPUNIT_TEST_SUITE(MountPointList_Test);
    CPPUNIT_TEST(testScanning);
    CPPUNIT_TEST(testStatusFile);
    CPPUNIT_TEST(testInitDisks);
    CPPUNIT_TEST_SUITE_END();

    static const std::string _prefix;

public:
    void testScanning();
    void testStatusFile();
    void testInitDisks();

    void init();
    void tearDown() override;

    framework::defaultimplementation::FakeClock _clock;

private:
    DeviceManager::UP newDeviceManager() {
        return DeviceManager::UP(
                new DeviceManager(
                        DeviceMapper::UP(new SimpleDeviceMapper),
                        _clock));
    }
};

CPPUNIT_TEST_SUITE_REGISTRATION(MountPointList_Test);

const std::string MountPointList_Test::_prefix("./vdsroot");

namespace {
    void run(const std::string& cmd) {
        CPPUNIT_ASSERT_MESSAGE(cmd, system(cmd.c_str()) == 0);
    }
}

void MountPointList_Test::init()
{
    tearDown();
    run("rm -rf "+_prefix);
    run("mkdir -p "+_prefix+"/disks");

    run("mkdir "+_prefix+"/disks/d0");    // Regular dir
    // disks/d1 intentionally missing
    run("mkdir "+_prefix+"/disks/D2");    // Wrongly named dir
    run("mkdir "+_prefix+"/disks/d3");    // Regular non-empty dir
    run("touch "+_prefix+"/disks/d3/foo");
    run("touch "+_prefix+"/disks/d4");    // Not a dir
    run("ln -s D2 "+_prefix+"/disks/d5"); // Symlink to dir
    run("ln -s d4 "+_prefix+"/disks/d6"); // Symlink to file
}

void MountPointList_Test::tearDown() {}

void MountPointList_Test::testScanning()
{
    init();
    MountPointList list(_prefix,
                        std::vector<vespalib::string>(),
                        DeviceManager::UP(
                                new DeviceManager(
                                        DeviceMapper::UP(new SimpleDeviceMapper),
                                        _clock)));
    list.scanForDisks();

        // Check that we got the expected entries.
    CPPUNIT_ASSERT_EQUAL(7u, list.getSize());

    for (uint32_t i=0; i<7u; ++i) {
        std::ostringstream ost;
        ost << _prefix << "/disks/d" << i;
        CPPUNIT_ASSERT_EQUAL(ost.str(), list[i].getPath());
    }

    // Note.. scanForDisks() should not in any circumstances access the
    // disks. Thus it should not know that d1 is inaccessible, or that d6
    // is actually a symlink to a file
    CPPUNIT_ASSERT_EQUAL(Device::OK,           list[0].getState());
    CPPUNIT_ASSERT_EQUAL(Device::NOT_FOUND,           list[1].getState());
    CPPUNIT_ASSERT_EQUAL(Device::NOT_FOUND,    list[2].getState());
    CPPUNIT_ASSERT_EQUAL(Device::OK,           list[3].getState());
    CPPUNIT_ASSERT_EQUAL(Device::PATH_FAILURE, list[4].getState());
    CPPUNIT_ASSERT_EQUAL(Device::OK,           list[5].getState());
    CPPUNIT_ASSERT_EQUAL(Device::OK,           list[6].getState());

    list.verifyHealthyDisks(-1);
    CPPUNIT_ASSERT_EQUAL(Device::OK,               list[0].getState());
    CPPUNIT_ASSERT_EQUAL(Device::NOT_FOUND,        list[1].getState());
    CPPUNIT_ASSERT_EQUAL(Device::NOT_FOUND,        list[2].getState());
    CPPUNIT_ASSERT_EQUAL(Device::INTERNAL_FAILURE, list[3].getState());
    CPPUNIT_ASSERT_EQUAL(Device::PATH_FAILURE,     list[4].getState());
    CPPUNIT_ASSERT_EQUAL(Device::OK,               list[5].getState());
    CPPUNIT_ASSERT_EQUAL(Device::PATH_FAILURE,     list[6].getState());
}

void MountPointList_Test::testStatusFile()
{
    init();
    std::string statusFileName(_prefix + "/disks.status");

    // Try reading non-existing file, and writing a file
    {
        MountPointList list(_prefix,
                            std::vector<vespalib::string>(),
                            DeviceManager::UP(
                                    new DeviceManager(
                                            DeviceMapper::UP(new SimpleDeviceMapper),
                                            _clock)));

        _clock.setAbsoluteTimeInSeconds(5678);
        list.scanForDisks();

        // File does not currently exist, that should be ok though.
        list.readFromFile();
        list.verifyHealthyDisks(-1);
        CPPUNIT_ASSERT_EQUAL(7u, list.getSize());
        list[5].addEvent(IOEvent(1234, Device::IO_FAILURE, "Argh", "Hmm"));
        CPPUNIT_ASSERT_EQUAL(Device::IO_FAILURE, list[5].getState());

        // Write to file.
        list.writeToFile();
    }

    // Check contents of file.
    {
        std::ifstream in(statusFileName.c_str());
        std::string line;
        CPPUNIT_ASSERT(std::getline(in, line));

        CPPUNIT_ASSERT_PREFIX(
                std::string(_prefix + "/disks/d1 1 5678 Disk not found "
                            "during scanning of disks directory"),
                line);
        CPPUNIT_ASSERT(std::getline(in, line));
        CPPUNIT_ASSERT_PREFIX(
                std::string(_prefix +"/disks/d2 1 5678 Disk not found during scanning of "
                            "disks directory"),
                line);
        CPPUNIT_ASSERT(std::getline(in, line));
        CPPUNIT_ASSERT_PREFIX(
                std::string(_prefix + "/disks/d3 4 5678 Foreign data in mountpoint. New "
                            "mountpoints added should be empty."),
                line);
        CPPUNIT_ASSERT(std::getline(in, line));
        CPPUNIT_ASSERT_PREFIX(
                std::string(_prefix + "/disks/d4 2 5678 File d4 in disks directory is not "
                            "a directory."),
                line);
        CPPUNIT_ASSERT(std::getline(in, line));
        CPPUNIT_ASSERT_PREFIX(std::string(_prefix + "/disks/d5 5 1234 Argh"),
                              line);
        CPPUNIT_ASSERT(std::getline(in, line));
        CPPUNIT_ASSERT_PREFIX(
                std::string(_prefix + "/disks/d6 2 5678 The path exist, but is not a "
                            "directory."),
                line);
        CPPUNIT_ASSERT(std::getline(in, line));
        CPPUNIT_ASSERT_EQUAL(std::string("EOF"), line);
    }

    // Starting over to get new device instances.
    // Scan disk, read file, and check that erronious disks are not used.
    {
        MountPointList list(_prefix,
                            std::vector<vespalib::string>(),
                            DeviceManager::UP(
                                    new DeviceManager(
                                            DeviceMapper::UP(new SimpleDeviceMapper),
                                            _clock)));
        list.scanForDisks();
        list.readFromFile();
            // Check that we got the expected entries.
        CPPUNIT_ASSERT_EQUAL(7u, list.getSize());

        // Note.. scanForDisks() should not under any circumstance access the
        // disks. Thus it should not know that d1 is inaccessible.
        CPPUNIT_ASSERT_EQUAL(Device::OK,            list[0].getState());
        CPPUNIT_ASSERT_EQUAL(Device::NOT_FOUND,     list[1].getState());
        CPPUNIT_ASSERT_EQUAL(Device::NOT_FOUND,     list[2].getState());
        CPPUNIT_ASSERT_EQUAL(Device::INTERNAL_FAILURE, list[3].getState());
        CPPUNIT_ASSERT_EQUAL(Device::PATH_FAILURE,  list[4].getState());
        CPPUNIT_ASSERT_EQUAL(Device::IO_FAILURE,    list[5].getState());
        CPPUNIT_ASSERT_EQUAL(Device::PATH_FAILURE,  list[6].getState());
    }
}

void MountPointList_Test::testInitDisks()
{
    vespalib::string d3target = "d3target";
    vespalib::string foodev = _prefix + "/foodev";
    vespalib::string bardev = _prefix + "/bardev";

    tearDown();
    run("rm -rf " + _prefix);
    run("mkdir -p " + _prefix + "/disks/d2");
    run("ln -s " + d3target + " " + _prefix + "/disks/d3");

    std::vector<vespalib::string> diskPaths {
        // disks/d0 should become a regular directory
        _prefix + "/disks/d0",
        // disks/d1 should be a symlink to /foo
        foodev,
        // disks/d2 should already be a directory
        "/ignored",
        // disks/d3 should already be a symlink
        "/ignored2"
    };

    MountPointList list(_prefix, diskPaths, newDeviceManager());
    list.initDisks();

    CPPUNIT_ASSERT(isDirectory(_prefix + "/disks"));
    CPPUNIT_ASSERT(isDirectory(_prefix + "/disks/d0"));
    CPPUNIT_ASSERT(isSymLink(_prefix + "/disks/d1"));
    CPPUNIT_ASSERT_EQUAL(foodev, readLink(_prefix + "/disks/d1"));
    CPPUNIT_ASSERT(isDirectory(_prefix + "/disks/d2"));
    CPPUNIT_ASSERT(isSymLink(_prefix + "/disks/d3"));
    CPPUNIT_ASSERT_EQUAL(d3target, readLink(_prefix + "/disks/d3"));
}

} // memfile

} // storage

<|endoftext|>


<commit_before>/*=========================================================================

  Program:   Insight Segmentation & Registration Toolkit
  Module:    itkEllipsoidInteriorExteriorSpatialFunctionTest.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) 2002 Insight Consortium. All rights reserved.
  See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notices for more information.

=========================================================================*/
#if defined(_MSC_VER)
#pragma warning ( disable : 4786 )
#endif

#include "itkEllipsoidInteriorExteriorSpatialFunction.h"
#include "vnl/vnl_matrix.h"

int itkEllipsoidInteriorExteriorSpatialFunctionTest(int, char* [] )
{
  std::cout << "itkEllipsoidInteriorExteriorSpatialFunction test start" << std::endl;

  // Test will create an ellipsoid (3-dimensional)
  const unsigned int dimension = 3;

  // Ellipsoid spatial function typedef
  typedef itk::EllipsoidInteriorExteriorSpatialFunction<3> TEllipsoidFunctionType;

  // Point position typedef
  typedef TEllipsoidFunctionType::InputType TEllipsoidFunctionVectorType;

  // Create an ellipsoid spatial function for the source image
  TEllipsoidFunctionType::Pointer spatialFunc = TEllipsoidFunctionType::New();
  // Define and set the axes lengths for the ellipsoid
  TEllipsoidFunctionVectorType axes;
  axes[0] = 40;
  axes[1] = 30;
  axes[2] = 20;
  spatialFunc->SetAxes(axes);

  // Define function doitkEllipsoidInteriorExteriorSpatialFunctionTest, which encapsulates ellipsoid.
  int xExtent = 50;
  int yExtent = 50;
  int zExtent = 50;

  // Define and set the center of the ellipsoid in the center of
  // the function doitkEllipsoidInteriorExteriorSpatialFunctionTest
  TEllipsoidFunctionVectorType center;
  center[0] = xExtent/2;
  center[1] = yExtent/2;
  center[2] = zExtent/2;
  spatialFunc->SetCenter(center);

  // Define the orientations of the ellipsoid axes
  // (0,1,0) corresponds to the axes of length axes[0]
  // (1,0,0) corresponds to the axes of length axes[1]
  // (0,0,1) corresponds to the axes of lenght axes[2]
  double data[] = {0, 1, 0, 1, 0, 0, 0, 0, 1};
  vnl_matrix<double> orientations (data, 3, 3);

  // Set the orientations of the ellipsoids
  spatialFunc->SetOrientations(orientations);

  // Evaluate all points in the spatial function and count the number of
  // pixels that are inside the sphere.
  double testPosition[dimension];  // position of a pixel in the function doitkEllipsoidInteriorExteriorSpatialFunctionTest

  bool functionValue;  // Value of pixel at a given position
  int interiorPixelCounter = 0;  // Count pixels inside ellipsoid

  for(int x = 0; x < xExtent; x++)
    {
    for(int y = 0; y < yExtent; y++)
      {
      for(int z =0; z < zExtent; z++)
        {
        testPosition[0] = x;
        testPosition[1] = y;
        testPosition[2] = z;
        functionValue = spatialFunc->Evaluate(testPosition);
        if(functionValue == 1)
          interiorPixelCounter ++;
        }
      }
    }

  // Evaluate the center of the ellipsoid, which is inside the ellipsoid and
  // should equal 1.
  testPosition[0] = center[0];
  testPosition[1] = center[1];
  testPosition[2] = center[2];
  functionValue = spatialFunc->Evaluate(testPosition);

  // Volume of ellipsoid using V=(4/3)*pi*(a/2)*(b/2)*(c/2)
  double volume = 4.18879013333*(axes[0]/2)*(axes[1]/2)*(axes[2]/2);

  // Percent difference in volume measurement and calculation
  double volumeError = (fabs(volume - interiorPixelCounter)/volume)*100;

  std::cout << spatialFunc;

  // 5% error was randomly chosen as a successful ellipsoid fill.
  // This should actually be some function of the image/ellipsoid size.
  if(volumeError <= 5 || functionValue == 1)
    {

    // With testing settings, results should yield:
    // calculated ellipsoid volume = 12566.4 pixels
    // measured ellipsoid volume = 12428 pixels
    // volume error = 1.10907%
    // function value = 1
    std::cout << "calculated ellipsoid volume = " << volume << std::endl
              << "measured ellipsoid volume = " << interiorPixelCounter << std::endl
              << "volume error = " << volumeError << "%" << std::endl
              << "function value = " << functionValue << std::endl
              << "itkEllipsoidSpatialFunction ended successfully!" << std::endl;
    return EXIT_SUCCESS;
    }
  else
    {
    std::cerr << "calculated ellipsoid volume = " << volume << std::endl
              << "measured ellipsoid volume = " << interiorPixelCounter << std::endl
              << "volume error = " << volumeError << "%" << std::endl
              << "function value = " << functionValue << std::endl
              << "itkEllipsoidSpatialFunction failed :(" << std::endl;
    return EXIT_FAILURE;
    }
}
<commit_msg>ENH: Call to Get Center and Get Axes to increase coverage<commit_after>/*=========================================================================

  Program:   Insight Segmentation & Registration Toolkit
  Module:    itkEllipsoidInteriorExteriorSpatialFunctionTest.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) 2002 Insight Consortium. All rights reserved.
  See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notices for more information.

=========================================================================*/
#if defined(_MSC_VER)
#pragma warning ( disable : 4786 )
#endif

#include "itkEllipsoidInteriorExteriorSpatialFunction.h"
#include "vnl/vnl_matrix.h"

int itkEllipsoidInteriorExteriorSpatialFunctionTest(int, char* [] )
{
  std::cout << "itkEllipsoidInteriorExteriorSpatialFunction test start" << std::endl;

  // Test will create an ellipsoid (3-dimensional)
  const unsigned int dimension = 3;

  // Ellipsoid spatial function typedef
  typedef itk::EllipsoidInteriorExteriorSpatialFunction<3> TEllipsoidFunctionType;

  // Point position typedef
  typedef TEllipsoidFunctionType::InputType TEllipsoidFunctionVectorType;

  // Create an ellipsoid spatial function for the source image
  TEllipsoidFunctionType::Pointer spatialFunc = TEllipsoidFunctionType::New();
  // Define and set the axes lengths for the ellipsoid
  TEllipsoidFunctionVectorType axes;
  axes[0] = 40;
  axes[1] = 30;
  axes[2] = 20;
  spatialFunc->SetAxes(axes);

  // Define function doitkEllipsoidInteriorExteriorSpatialFunctionTest, which encapsulates ellipsoid.
  int xExtent = 50;
  int yExtent = 50;
  int zExtent = 50;

  // Define and set the center of the ellipsoid in the center of
  // the function doitkEllipsoidInteriorExteriorSpatialFunctionTest
  TEllipsoidFunctionVectorType center;
  center[0] = xExtent/2;
  center[1] = yExtent/2;
  center[2] = zExtent/2;
  spatialFunc->SetCenter(center);

  // Define the orientations of the ellipsoid axes
  // (0,1,0) corresponds to the axes of length axes[0]
  // (1,0,0) corresponds to the axes of length axes[1]
  // (0,0,1) corresponds to the axes of lenght axes[2]
  double data[] = {0, 1, 0, 1, 0, 0, 0, 0, 1};
  vnl_matrix<double> orientations (data, 3, 3);

  // Set the orientations of the ellipsoids
  spatialFunc->SetOrientations(orientations);

  // Evaluate all points in the spatial function and count the number of
  // pixels that are inside the sphere.
  double testPosition[dimension];  // position of a pixel in the function doitkEllipsoidInteriorExteriorSpatialFunctionTest

  bool functionValue;  // Value of pixel at a given position
  int interiorPixelCounter = 0;  // Count pixels inside ellipsoid

  for(int x = 0; x < xExtent; x++)
    {
    for(int y = 0; y < yExtent; y++)
      {
      for(int z =0; z < zExtent; z++)
        {
        testPosition[0] = x;
        testPosition[1] = y;
        testPosition[2] = z;
        functionValue = spatialFunc->Evaluate(testPosition);
        if(functionValue == 1)
          interiorPixelCounter ++;
        }
      }
    }

  // Evaluate the center of the ellipsoid, which is inside the ellipsoid and
  // should equal 1.
  testPosition[0] = center[0];
  testPosition[1] = center[1];
  testPosition[2] = center[2];
  functionValue = spatialFunc->Evaluate(testPosition);

  // Volume of ellipsoid using V=(4/3)*pi*(a/2)*(b/2)*(c/2)
  double volume = 4.18879013333*(axes[0]/2)*(axes[1]/2)*(axes[2]/2);

  // Percent difference in volume measurement and calculation
  double volumeError = (fabs(volume - interiorPixelCounter)/volume)*100;

  std::cout << spatialFunc;

  // 5% error was randomly chosen as a successful ellipsoid fill.
  // This should actually be some function of the image/ellipsoid size.
  if(volumeError <= 5 || functionValue == 1)
    {

    // With testing settings, results should yield:
    // calculated ellipsoid volume = 12566.4 pixels
    // measured ellipsoid volume = 12428 pixels
    // volume error = 1.10907%
    // function value = 1
    std::cout << "calculated ellipsoid volume = " << volume << std::endl
              << "measured ellipsoid volume = " << interiorPixelCounter << std::endl
              << "volume error = " << volumeError << "%" << std::endl
              << "function value = " << functionValue << std::endl
              << "center location = (" << spatialFunc->GetCenter()[0] << ", " << spatialFunc->GetCenter()[0]
              << ", " << spatialFunc->GetCenter()[2] << ")" << std::endl
              << "major axis length = " << spatialFunc->GetAxes()[0] << " minor axis 1 length = "
              << spatialFunc->GetAxes()[1] << " minor axis 2 length = " << spatialFunc->GetAxes()[2] << std::endl
              << "itkEllipsoidSpatialFunction ended successfully!" << std::endl;
    return EXIT_SUCCESS;
    }
  else
    {
    std::cerr << "calculated ellipsoid volume = " << volume << std::endl
              << "measured ellipsoid volume = " << interiorPixelCounter << std::endl
              << "volume error = " << volumeError << "%" << std::endl
              << "function value = " << functionValue << std::endl
              << "center location = (" << spatialFunc->GetCenter()[0] << ", " << spatialFunc->GetCenter()[0]
              << ", " << spatialFunc->GetCenter()[2] << ")" << std::endl
              << "major axis length = " << spatialFunc->GetAxes()[0] << " minor axis 1 length = "
              << spatialFunc->GetAxes()[1] << " minor axis 2 length = " << spatialFunc->GetAxes()[2] << std::endl
              << "itkEllipsoidSpatialFunction failed :(" << std::endl;
    return EXIT_FAILURE;
    }
}
<|endoftext|>