[Positioning] Add logging support
Add interface InputLogMedium and class InputLogCSV. Input: Add logging support. UserInterface: Add logging options. Configuration: - Rename functions (suppress "get_"). - Add functions to allow multiple values in one option (needed by logging options): - value_exists_in_string_vector() - string_vector_value() InputCSV: Add a destructor. posexcept.hh: Add no_log_csv_file exception. TestUtil: - Improve set_up(). - Add functions used in InputLogCSV_test: - functions to compare Request & Co, - functions to compare the sizes of two files.
This commit is contained in:
parent
8257e9e67d
commit
a5aa1af433
|
@ -31,8 +31,10 @@ TARGET = owlps-positioning
|
|||
OBJ = posutil.o stock.o timestamp.o point3d.o referencepoint.o \
|
||||
waypoint.o building.o area.o wifidevice.o accesspoint.o \
|
||||
mobile.o measurement.o calibrationmeasurement.o request.o \
|
||||
inputcsv.o configuration.o userinterface.o input.o
|
||||
configuration.o userinterface.o input.o \
|
||||
inputcsv.o inputlogcsv.o
|
||||
OBJ_NOTEST = posexcept.o
|
||||
INTERFACES = inputmedium.hh inputlogmedium.hh
|
||||
|
||||
TESTS_XX = $(TESTS_DIR)/tests.cc
|
||||
TESTS_OBJ = $(TESTS_DIR)/tests.o
|
||||
|
@ -67,6 +69,7 @@ measurement.o: accesspoint.o
|
|||
calibrationmeasurement.o: measurement.o referencepoint.o
|
||||
request.o: timestamp.o measurement.o
|
||||
inputcsv.o: inputmedium.hh request.o stock.o
|
||||
inputlogcsv.o: inputlogmedium.hh request.o
|
||||
input.o: posexcept.o
|
||||
|
||||
# Specific targets
|
||||
|
@ -114,7 +117,7 @@ style:
|
|||
$(OBJ:.o=.cc) \
|
||||
$(OBJ_NOTEST:.o=.hh) \
|
||||
$(OBJ_NOTEST:.o=.cc) \
|
||||
inputmedium.hh \
|
||||
$(INTERFACES) \
|
||||
$(TESTS_DIR)/*.hh \
|
||||
$(TESTS_DIR)/*.cc
|
||||
|
||||
|
@ -122,4 +125,4 @@ check:
|
|||
@$(CPPCHECK) \
|
||||
$(OBJ:.o=.hh) $(OBJ:.o=.cc) \
|
||||
$(OBJ_NOTEST:.o=.hh) $(OBJ_NOTEST:.o=.cc) \
|
||||
inputmedium.hh
|
||||
$(INTERFACES)
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
#include "configuration.hh"
|
||||
|
||||
using namespace std ;
|
||||
namespace po = boost::program_options ;
|
||||
|
||||
|
||||
|
@ -19,7 +20,7 @@ po::variables_map& Configuration::getw_configuration()
|
|||
}
|
||||
|
||||
|
||||
bool Configuration::is_configured(const std::string &key)
|
||||
bool Configuration::is_configured(const string &key)
|
||||
{
|
||||
if (configuration.count(key))
|
||||
return true ;
|
||||
|
@ -28,13 +29,36 @@ bool Configuration::is_configured(const std::string &key)
|
|||
|
||||
|
||||
const std::string&
|
||||
Configuration::get_string_value(const std::string &key)
|
||||
Configuration::string_value(const string &key)
|
||||
{
|
||||
return configuration[key].as<std::string>() ;
|
||||
return configuration[key].as<string>() ;
|
||||
}
|
||||
|
||||
|
||||
int Configuration::get_int_value(const std::string &key)
|
||||
int Configuration::int_value(const string &key)
|
||||
{
|
||||
return configuration[key].as<int>() ;
|
||||
}
|
||||
|
||||
|
||||
bool Configuration::
|
||||
value_exists_in_string_vector(const string &key, const string &value)
|
||||
{
|
||||
if (! is_configured(key))
|
||||
return false ;
|
||||
|
||||
vector<string> key_values = configuration[key].as< vector<string> >() ;
|
||||
|
||||
for (vector<string>::const_iterator i = key_values.begin() ;
|
||||
i != key_values.end() ; ++i)
|
||||
if (*i == value)
|
||||
return true ;
|
||||
|
||||
return false ;
|
||||
}
|
||||
|
||||
|
||||
const vector<string>& Configuration::string_vector_value(const string &key)
|
||||
{
|
||||
return configuration[key].as< vector<string> >() ;
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
#define _OWLPS_POSITIONING_CONFIGURATION_HH_
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <boost/program_options/variables_map.hpp>
|
||||
|
||||
/// Stocks the configuration of the program
|
||||
|
@ -18,9 +19,14 @@ public:
|
|||
/// Checks if the key exists in the configuration
|
||||
static bool is_configured(const std::string &key) ;
|
||||
/// Get the string value corresponding to \em key
|
||||
static const std::string& get_string_value(const std::string &key) ;
|
||||
static const std::string& string_value(const std::string &key) ;
|
||||
/// Get the int value corresponding to \em key
|
||||
static int get_int_value(const std::string &key) ;
|
||||
static int int_value(const std::string &key) ;
|
||||
static bool value_exists_in_string_vector(
|
||||
const std::string &key,
|
||||
const std::string &value) ;
|
||||
static const std::vector<std::string>&
|
||||
string_vector_value(const std::string &key) ;
|
||||
} ;
|
||||
|
||||
#endif // _OWLPS_POSITIONING_CONFIGURATION_HH_
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
#include "input.hh"
|
||||
#include "inputcsv.hh"
|
||||
#include "inputlogcsv.hh"
|
||||
#include "request.hh"
|
||||
#include "configuration.hh"
|
||||
#include "posexcept.hh"
|
||||
|
@ -14,6 +15,7 @@ Input::Input()
|
|||
{
|
||||
medium = NULL ;
|
||||
initialise_input_medium() ;
|
||||
initialise_log_media() ;
|
||||
}
|
||||
|
||||
|
||||
|
@ -33,14 +35,14 @@ void Input::initialise_input_medium()
|
|||
throw no_input_medium() ;
|
||||
|
||||
const string &medium_name =
|
||||
Configuration::get_string_value("input.medium") ;
|
||||
Configuration::string_value("input.medium") ;
|
||||
|
||||
if (medium_name == "CSV")
|
||||
{
|
||||
if (! Configuration::is_configured("input.csv-file"))
|
||||
throw no_input_csv_file() ;
|
||||
medium = new
|
||||
InputCSV(Configuration::get_string_value("input.csv-file")) ;
|
||||
InputCSV(Configuration::string_value("input.csv-file")) ;
|
||||
}
|
||||
|
||||
else
|
||||
|
@ -48,11 +50,49 @@ void Input::initialise_input_medium()
|
|||
}
|
||||
|
||||
|
||||
void Input::initialise_log_media()
|
||||
{
|
||||
if (! Configuration::is_configured("log.medium"))
|
||||
return ;
|
||||
|
||||
if (Configuration::value_exists_in_string_vector("log.medium", "none"))
|
||||
return ;
|
||||
|
||||
const vector<string> &media_names =
|
||||
Configuration::string_vector_value("log.medium") ;
|
||||
|
||||
for (vector<string>::const_iterator i = media_names.begin() ;
|
||||
i != media_names.end() ; ++i)
|
||||
{
|
||||
if (*i == "CSV")
|
||||
initialise_log_csv() ;
|
||||
|
||||
else
|
||||
throw input_medium_type_unknown(*i) ;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Input::initialise_log_csv()
|
||||
{
|
||||
if (! Configuration::is_configured("log.csv-file"))
|
||||
throw no_log_csv_file() ;
|
||||
|
||||
log_media.push_back(
|
||||
new InputLogCSV(
|
||||
Configuration::string_value("log.csv-file"))) ;
|
||||
}
|
||||
|
||||
|
||||
const Request& Input::get_next_request() const
|
||||
{
|
||||
if (medium == NULL)
|
||||
throw null_input_medium() ;
|
||||
return medium->get_next_request() ;
|
||||
if (! eof())
|
||||
{
|
||||
medium->get_next_request() ;
|
||||
log_current_request() ;
|
||||
}
|
||||
|
||||
return medium->get_current_request() ;
|
||||
}
|
||||
|
||||
|
||||
|
@ -62,3 +102,11 @@ bool Input::eof() const
|
|||
throw null_input_medium() ;
|
||||
return medium->eof() ;
|
||||
}
|
||||
|
||||
|
||||
void Input::log_current_request() const
|
||||
{
|
||||
for (vector<InputLogMedium*>::const_iterator i = log_media.begin() ;
|
||||
i != log_media.end() ; ++i)
|
||||
(*i)->log_request(medium->get_current_request()) ;
|
||||
}
|
||||
|
|
|
@ -2,17 +2,24 @@
|
|||
#define _OWLPS_POSITIONING_INPUT_HH_
|
||||
|
||||
class InputMedium ;
|
||||
class InputLogMedium ;
|
||||
class Request ;
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
/// Handles the inputs
|
||||
class Input
|
||||
{
|
||||
protected:
|
||||
InputMedium *medium ; ///< Input medium used
|
||||
/// List of input log media used
|
||||
std::vector<InputLogMedium*> log_media ;
|
||||
|
||||
void initialise_input_medium(void) ;
|
||||
void initialise_log_media(void) ;
|
||||
void initialise_log_csv(void) ;
|
||||
void log_current_request(void) const ;
|
||||
|
||||
public:
|
||||
Input(void) ;
|
||||
|
|
|
@ -38,6 +38,12 @@ InputCSV::InputCSV(const string &filename)
|
|||
}
|
||||
|
||||
|
||||
InputCSV::~InputCSV()
|
||||
{
|
||||
input_file.close() ;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* *** Operations *** */
|
||||
|
||||
|
|
|
@ -28,6 +28,7 @@ protected:
|
|||
public:
|
||||
/// Constructs an InputCSV from a CSV input file name
|
||||
InputCSV(const std::string &filename) ;
|
||||
~InputCSV(void) ;
|
||||
|
||||
/** @name Read accessors */
|
||||
//@{
|
||||
|
|
|
@ -0,0 +1,81 @@
|
|||
#include "inputlogcsv.hh"
|
||||
#include "posexcept.hh"
|
||||
#include "mobile.hh"
|
||||
|
||||
#include <sstream>
|
||||
|
||||
using namespace std ;
|
||||
using std::tr1::unordered_map ;
|
||||
|
||||
|
||||
|
||||
/* *** Constructors *** */
|
||||
|
||||
|
||||
/**
|
||||
* Prepares the InputLogCSV to write to a CSV file.
|
||||
* @param filename The name of the file to open.
|
||||
* @throw error_opening_input_file if the file cannot be opened.
|
||||
*/
|
||||
InputLogCSV::InputLogCSV(const string &filename)
|
||||
{
|
||||
log_file_name = filename ;
|
||||
|
||||
log_file.open(log_file_name.c_str()) ;
|
||||
if (! log_file)
|
||||
throw error_opening_input_file(log_file_name) ;
|
||||
}
|
||||
|
||||
|
||||
InputLogCSV::~InputLogCSV()
|
||||
{
|
||||
log_file.close() ;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* *** Operations *** */
|
||||
|
||||
|
||||
/**
|
||||
* @return true if the request has been logged successfuly, or false
|
||||
* if not.
|
||||
*/
|
||||
bool InputLogCSV::log_request(const Request &request)
|
||||
{
|
||||
if (! log_file)
|
||||
return false ;
|
||||
|
||||
log_file << request_to_csv(request).c_str() ;
|
||||
return true ;
|
||||
}
|
||||
|
||||
|
||||
const string InputLogCSV::request_to_csv(const Request &request) const
|
||||
{
|
||||
ostringstream csv_line ;
|
||||
if (request.get_mobile() != NULL)
|
||||
csv_line << request.get_mobile()->get_mac_addr() ;
|
||||
csv_line << ';' << request.get_timestamp().get_timestamp_ms() ;
|
||||
csv_line << ";0;0;0;0" ; // TODO: handle calibration request
|
||||
|
||||
const unordered_map<string, Measurement> &measurements =
|
||||
request.get_measurements() ;
|
||||
for (unordered_map<string, Measurement>::const_iterator i
|
||||
= measurements.begin() ; i != measurements.end() ; ++i)
|
||||
{
|
||||
const vector<int> &ss_list = i->second.get_ss_list() ;
|
||||
const string &ap_mac = i->second.get_ap() != NULL
|
||||
? i->second.get_ap()->get_mac_addr()
|
||||
: "" ;
|
||||
for (vector<int>::const_iterator i = ss_list.begin() ;
|
||||
i != ss_list.end() ; ++i)
|
||||
{
|
||||
csv_line << ';' << ap_mac ;
|
||||
csv_line << ';' << *i ;
|
||||
}
|
||||
}
|
||||
|
||||
csv_line << '\n' ;
|
||||
return csv_line.str() ;
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
#ifndef _OWLPS_POSITIONING_INPUTLOGCSV_HH_
|
||||
#define _OWLPS_POSITIONING_INPUTLOGCSV_HH_
|
||||
|
||||
#include "inputlogmedium.hh"
|
||||
|
||||
#include <string>
|
||||
#include <fstream>
|
||||
|
||||
/// Log Request to a CSV file
|
||||
class InputLogCSV: public InputLogMedium
|
||||
{
|
||||
protected:
|
||||
std::string log_file_name ;
|
||||
std::ofstream log_file ;
|
||||
|
||||
const std::string request_to_csv(const Request &request) const ;
|
||||
|
||||
public:
|
||||
InputLogCSV(const std::string &filename) ;
|
||||
~InputLogCSV(void) ;
|
||||
|
||||
/** @name Operations */
|
||||
//@{
|
||||
bool log_request(const Request &request) ;
|
||||
//@}
|
||||
} ;
|
||||
|
||||
#endif // _OWLPS_POSITIONING_INPUTLOGCSV_HH_
|
|
@ -0,0 +1,22 @@
|
|||
#ifndef _OWLPS_POSITIONING_INPUTLOGMEDIUM_HH_
|
||||
#define _OWLPS_POSITIONING_INPUTLOGMEDIUM_HH_
|
||||
|
||||
#include "request.hh"
|
||||
|
||||
/// Super class of all input log media
|
||||
/**
|
||||
* Provide interface for input log media, i.e. to log Request received
|
||||
* by the InputMedium.
|
||||
*/
|
||||
class InputLogMedium
|
||||
{
|
||||
public:
|
||||
virtual ~InputLogMedium(void) {}
|
||||
|
||||
/** @name Operations */
|
||||
//@{
|
||||
virtual bool log_request(const Request &request) = 0 ;
|
||||
//@} // End Operations
|
||||
} ;
|
||||
|
||||
#endif // _OWLPS_POSITIONING_INPUTLOGMEDIUM_HH_
|
|
@ -49,6 +49,12 @@ const char* no_input_csv_file::what() const throw()
|
|||
}
|
||||
|
||||
|
||||
const char* no_log_csv_file::what() const throw()
|
||||
{
|
||||
return "No log CSV file specified in the configuration!" ;
|
||||
}
|
||||
|
||||
|
||||
error_opening_input_file::
|
||||
error_opening_input_file(const string &_file_name) throw():
|
||||
file_name(_file_name) {}
|
||||
|
|
|
@ -50,6 +50,13 @@ public:
|
|||
} ;
|
||||
|
||||
|
||||
class no_log_csv_file: public std::exception
|
||||
{
|
||||
public:
|
||||
const char* what() const throw() ;
|
||||
} ;
|
||||
|
||||
|
||||
class error_opening_input_file: public std::exception
|
||||
{
|
||||
private:
|
||||
|
|
|
@ -0,0 +1,89 @@
|
|||
#include <cxxtest/TestSuite.h>
|
||||
|
||||
#include "inputlogcsv.hh"
|
||||
|
||||
#include <vector>
|
||||
|
||||
class InputLogCSV_test: public CxxTest::TestSuite
|
||||
{
|
||||
private:
|
||||
std::string csv_file_name ;
|
||||
std::string log_file_name ;
|
||||
|
||||
public:
|
||||
|
||||
InputLogCSV_test(void)
|
||||
{
|
||||
// If we cannot open the file, we want to stop the test
|
||||
CxxTest::setAbortTestOnFail(true) ;
|
||||
|
||||
// Clear the stock
|
||||
Stock::clear() ;
|
||||
|
||||
csv_file_name = "/tmp/InputLogCSV_test_csv_file.csv" ;
|
||||
TestUtil::create_test_csv_file(csv_file_name) ;
|
||||
|
||||
log_file_name = "/tmp/InputLogCSV_test_log_file.csv" ;
|
||||
|
||||
// Back to the normal behaviour (i.e. do not abort on fail)
|
||||
CxxTest::setAbortTestOnFail(false) ;
|
||||
}
|
||||
|
||||
|
||||
~InputLogCSV_test(void)
|
||||
{
|
||||
TestUtil::remove_file(csv_file_name) ;
|
||||
TestUtil::remove_file(log_file_name) ;
|
||||
Stock::clear() ;
|
||||
}
|
||||
|
||||
|
||||
static InputLogCSV_test* createSuite(void)
|
||||
{
|
||||
return new InputLogCSV_test() ;
|
||||
}
|
||||
|
||||
|
||||
static void destroySuite(InputLogCSV_test *suite)
|
||||
{
|
||||
delete suite ;
|
||||
}
|
||||
|
||||
|
||||
void test_inputlogcsv(void)
|
||||
{
|
||||
// Note: we need to dynamically create and delete an InputLogCSV
|
||||
// instance in order to be able to close the file (and therefore
|
||||
// flush the stream) before to read it with InputCSV
|
||||
InputLogCSV *inputlogcsv1 = new InputLogCSV(log_file_name) ;
|
||||
for (std::vector<Request>::const_iterator i =
|
||||
TestUtil::requests.begin() ;
|
||||
i != TestUtil::requests.end() ; ++i)
|
||||
inputlogcsv1->log_request(*i) ;
|
||||
delete inputlogcsv1 ; // Close the output file
|
||||
|
||||
// Even if data is not in the same order, size of the two files
|
||||
// must be identical
|
||||
TS_ASSERT(TestUtil::file_size_equals(csv_file_name, log_file_name)) ;
|
||||
|
||||
// Read the two files and compare to the reference Request list
|
||||
InputCSV inputcsv_csv(csv_file_name) ;
|
||||
InputCSV inputcsv_log(log_file_name) ;
|
||||
for (std::vector<Request>::const_iterator i =
|
||||
TestUtil::requests.begin() ;
|
||||
i != TestUtil::requests.end() ; ++i)
|
||||
{
|
||||
Stock::clear() ;
|
||||
Request request_csv = inputcsv_csv.get_next_request() ;
|
||||
TS_ASSERT(TestUtil::request_equals(*i, request_csv)) ;
|
||||
|
||||
Stock::clear() ;
|
||||
Request request_log = inputcsv_log.get_next_request() ;
|
||||
TS_ASSERT(TestUtil::request_equals(*i, request_log)) ;
|
||||
}
|
||||
|
||||
TS_ASSERT(inputcsv_csv.eof()) ;
|
||||
TS_ASSERT(inputcsv_log.eof()) ;
|
||||
}
|
||||
|
||||
} ;
|
|
@ -1,11 +1,9 @@
|
|||
#include "testutil.hh"
|
||||
#include <cxxtest/TestSuite.h>
|
||||
|
||||
#include "measurement.hh"
|
||||
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
#include <boost/tr1/unordered_map.hpp>
|
||||
#include <sys/stat.h>
|
||||
|
||||
using namespace std ;
|
||||
using std::tr1::unordered_map ;
|
||||
|
@ -28,15 +26,22 @@ void TestUtil::set_up()
|
|||
tear_down() ;
|
||||
|
||||
// Create mobile list
|
||||
mobiles.push_back(Mobile("192.168.0.42", "aa:bb:cc:dd:ee:ff")) ;
|
||||
mobiles.push_back(Mobile("192.168.1.87", "aa:bb:cc:dd:ee:77")) ;
|
||||
Mobile mobile1 ;
|
||||
mobile1.set_mac_addr("aa:bb:cc:dd:ee:ff") ;
|
||||
mobiles.push_back(mobile1) ;
|
||||
mobile1.set_mac_addr("aa:bb:cc:dd:ee:77") ;
|
||||
mobiles.push_back(mobile1) ;
|
||||
|
||||
// Create AP list
|
||||
aps.push_back(AccessPoint(Point3D(1,2,3), "10.0.0.1", "11:22:33:44:55:01")) ;
|
||||
aps.push_back(AccessPoint(Point3D(4,5,6), "10.0.0.2", "11:22:33:44:55:02")) ;
|
||||
aps.push_back(AccessPoint(Point3D(7,8,9), "10.0.0.3", "11:22:33:44:55:03")) ;
|
||||
AccessPoint ap1 ;
|
||||
ap1.set_mac_addr("11:22:33:44:55:01") ;
|
||||
aps.push_back(ap1) ;
|
||||
ap1.set_mac_addr("11:22:33:44:55:02") ;
|
||||
aps.push_back(ap1) ;
|
||||
ap1.set_mac_addr("11:22:33:44:55:03") ;
|
||||
aps.push_back(ap1) ;
|
||||
|
||||
// Create measurement list
|
||||
// Create request list
|
||||
vector < unordered_map<string,Measurement> > measurements(3) ;
|
||||
Measurement measurement1 ;
|
||||
|
||||
|
@ -91,9 +96,12 @@ void TestUtil::set_up()
|
|||
timestamps.push_back(Timestamp(1265120912345)) ;
|
||||
|
||||
// Create request list
|
||||
requests.push_back(Request(timestamps[0], measurements[0])) ;
|
||||
requests.push_back(Request(timestamps[1], measurements[1])) ;
|
||||
requests.push_back(Request(timestamps[2], measurements[2])) ;
|
||||
requests.push_back(Request(&mobiles[0], timestamps[0],
|
||||
measurements[0])) ;
|
||||
requests.push_back(Request(&mobiles[1], timestamps[1],
|
||||
measurements[1])) ;
|
||||
requests.push_back(Request(&mobiles[0], timestamps[2],
|
||||
measurements[2])) ;
|
||||
}
|
||||
|
||||
|
||||
|
@ -241,3 +249,114 @@ create_test_csv_file(const string &file_name, bool with_spaces)
|
|||
// Create and fill the test CSV file
|
||||
fill_file(file_name, csv_lines) ;
|
||||
}
|
||||
|
||||
|
||||
// Test equality of two Request comparing pointed values instead of
|
||||
// pointers and taking care of the unordered_map
|
||||
bool TestUtil::request_equals(const Request &first,
|
||||
const Request &second)
|
||||
{
|
||||
// Try a classical comparison
|
||||
if (first == second)
|
||||
return true ;
|
||||
|
||||
// Compare timestamp
|
||||
if (first.get_timestamp() != second.get_timestamp())
|
||||
return false ;
|
||||
|
||||
// Compare mobile values
|
||||
if (first.get_mobile() == NULL || second.get_mobile() == NULL)
|
||||
{
|
||||
if (first.get_mobile() != NULL || second.get_mobile() != NULL)
|
||||
return false ;
|
||||
}
|
||||
else if (*first.get_mobile() != *second.get_mobile())
|
||||
return false ;
|
||||
|
||||
// Compare measurements
|
||||
if (first.get_measurements() != second.get_measurements())
|
||||
if (! measurements_unordered_map_equals(first.get_measurements(),
|
||||
second.get_measurements()))
|
||||
return false ;
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
|
||||
// Test equality of two unordered_map<string,Measurement>
|
||||
bool TestUtil::
|
||||
measurements_unordered_map_equals(
|
||||
unordered_map<string,Measurement> first,
|
||||
unordered_map<string,Measurement> second)
|
||||
{
|
||||
if (first.size() != second.size())
|
||||
return false ;
|
||||
|
||||
// For each element in 'first', we look for the same element
|
||||
// in 'second'
|
||||
for (unordered_map<string,Measurement>::const_iterator i =
|
||||
first.begin() ; i != first.end() ; ++i)
|
||||
{
|
||||
unordered_map<string,Measurement>::const_iterator
|
||||
second_measurement = second.find(i->first) ;
|
||||
if (second_measurement == second.end())
|
||||
return false ;
|
||||
if (! measurement_equals(i->second, second_measurement->second))
|
||||
return false ;
|
||||
}
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
|
||||
// Test equality of two Measurement comparing pointed values instead of
|
||||
// pointers
|
||||
bool TestUtil::measurement_equals(const Measurement &first,
|
||||
const Measurement &second)
|
||||
{
|
||||
// Try a classical comparison
|
||||
if (first == second)
|
||||
return true ;
|
||||
|
||||
// Compare average_ss
|
||||
if (first.get_average_ss() != second.get_average_ss())
|
||||
return false ;
|
||||
|
||||
// Compare ap values
|
||||
if (first.get_ap() == NULL || second.get_ap() == NULL)
|
||||
{
|
||||
if (first.get_ap() != NULL || second.get_ap() != NULL)
|
||||
return false ;
|
||||
}
|
||||
else if (*first.get_ap() != *second.get_ap())
|
||||
return false ;
|
||||
|
||||
// Compare ss_list
|
||||
if (first.get_ss_list() != second.get_ss_list())
|
||||
return false ;
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
|
||||
bool TestUtil::file_size_equals(const string &file1_name,
|
||||
const string &file2_name)
|
||||
{
|
||||
try
|
||||
{
|
||||
return (file_size(file1_name) == file_size(file2_name)) ;
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
return false ;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
off_t TestUtil::file_size(const string &file_name)
|
||||
{
|
||||
struct stat file_info ;
|
||||
if (stat(file_name.c_str(), &file_info) != 0)
|
||||
throw "Cannot get information for file `" + file_name + "`!" ;
|
||||
return file_info.st_size ;
|
||||
}
|
||||
|
|
|
@ -4,9 +4,11 @@
|
|||
#include "accesspoint.hh"
|
||||
#include "mobile.hh"
|
||||
#include "request.hh"
|
||||
#include "measurement.hh"
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <boost/tr1/unordered_map.hpp>
|
||||
|
||||
class TestUtil
|
||||
{
|
||||
|
@ -24,6 +26,20 @@ public:
|
|||
|
||||
static void create_test_csv_file(const std::string &file_name,
|
||||
bool with_spaces = false) ;
|
||||
|
||||
static bool request_equals(const Request &first,
|
||||
const Request &second) ;
|
||||
static bool measurements_unordered_map_equals(
|
||||
std::tr1::unordered_map<std::string,Measurement> first,
|
||||
std::tr1::unordered_map<std::string,Measurement> second) ;
|
||||
static bool measurement_equals(const Measurement &first,
|
||||
const Measurement &second) ;
|
||||
|
||||
|
||||
static bool file_size_equals(const std::string &file1_name,
|
||||
const std::string &file2_name) ;
|
||||
static off_t file_size(const std::string &file_name) ;
|
||||
|
||||
} ;
|
||||
|
||||
#endif // _OWLPS_POSITIONING_TESTS_TESTUTIL_HH_
|
||||
|
|
|
@ -67,8 +67,8 @@ public:
|
|||
TS_ASSERT(Configuration::is_configured("server.port")) ;
|
||||
TS_ASSERT(Configuration::is_configured("config-file")) ;
|
||||
|
||||
TS_ASSERT_EQUALS(Configuration::get_int_value("server.port"), 42) ;
|
||||
TS_ASSERT_EQUALS(Configuration::get_string_value("config-file"),
|
||||
TS_ASSERT_EQUALS(Configuration::int_value("server.port"), 42) ;
|
||||
TS_ASSERT_EQUALS(Configuration::string_value("config-file"),
|
||||
config_file_name) ;
|
||||
}
|
||||
|
||||
|
|
|
@ -71,12 +71,19 @@ void UserInterface::fill_file_options()
|
|||
// Server options
|
||||
("server.port,l", po::value<int>()
|
||||
->default_value(DEFAULT_LISTENING_PORT),
|
||||
"Server listening port")
|
||||
"Server listening port.")
|
||||
// Input options
|
||||
("input.medium,I", po::value<string>(),
|
||||
"Medium from which requests are read")
|
||||
"Medium from which requests are read. Allowed: CSV.")
|
||||
("input.csv-file,C", po::value<string>(),
|
||||
"CSV file to use for input (when input.medium = CSV)")
|
||||
"CSV file to use for input (when input.medium = CSV).")
|
||||
// Log options
|
||||
("log.medium,L", po::value< vector<string> >()->composing(),
|
||||
"Medium to which the requests will be logged. You can specify \
|
||||
this option more than once. Allowed: none, CSV. The `none` value \
|
||||
completely disables logging.")
|
||||
("log.csv-file", po::value<string>(),
|
||||
"CSV file to use for logging (when log.medium = CSV).")
|
||||
;
|
||||
}
|
||||
|
||||
|
@ -88,7 +95,7 @@ void UserInterface::parse_options()
|
|||
|
||||
// Was the config file name specified on the command line?
|
||||
if (Configuration::is_configured("config-file"))
|
||||
config_file_name = Configuration::get_string_value("config-file") ;
|
||||
config_file_name = Configuration::string_value("config-file") ;
|
||||
|
||||
parse_file() ;
|
||||
|
||||
|
|
Loading…
Reference in New Issue