2016-09-29 16:31:22 +00:00
|
|
|
/*!
|
|
|
|
* \file ttff_gps_l1.cc
|
|
|
|
* \brief This class implements a test for measuring
|
|
|
|
* the Time-To-First-Fix
|
|
|
|
* \author Carles Fernandez-Prades, 2016. cfernandez(at)cttc.es
|
|
|
|
*
|
|
|
|
*
|
|
|
|
* -------------------------------------------------------------------------
|
|
|
|
*
|
|
|
|
* Copyright (C) 2010-2016 (see AUTHORS file for a list of contributors)
|
|
|
|
*
|
|
|
|
* GNSS-SDR is a software defined Global Navigation
|
|
|
|
* Satellite Systems receiver
|
|
|
|
*
|
|
|
|
* This file is part of GNSS-SDR.
|
|
|
|
*
|
|
|
|
* GNSS-SDR is free software: you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
|
|
* (at your option) any later version.
|
|
|
|
*
|
|
|
|
* GNSS-SDR is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with GNSS-SDR. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
*
|
|
|
|
* -------------------------------------------------------------------------
|
|
|
|
*/
|
|
|
|
|
2016-10-01 08:25:29 +00:00
|
|
|
#include <errno.h>
|
|
|
|
#include <sys/types.h>
|
|
|
|
#include <sys/ipc.h>
|
|
|
|
#include <sys/msg.h>
|
2016-09-29 17:06:17 +00:00
|
|
|
#include <ctime>
|
|
|
|
#include <chrono>
|
2016-10-01 09:26:59 +00:00
|
|
|
#include <numeric>
|
2016-09-29 16:31:22 +00:00
|
|
|
#include <string>
|
2016-09-29 17:06:17 +00:00
|
|
|
#include <thread>
|
2016-09-29 16:31:22 +00:00
|
|
|
#include "in_memory_configuration.h"
|
2016-10-01 08:25:29 +00:00
|
|
|
#include "file_configuration.h"
|
2016-09-29 16:31:22 +00:00
|
|
|
#include "concurrent_queue.h"
|
|
|
|
#include "concurrent_map.h"
|
2016-09-29 17:06:17 +00:00
|
|
|
#include "control_thread.h"
|
2016-09-29 18:15:50 +00:00
|
|
|
#include "gnss_flowgraph.h"
|
2016-09-29 16:31:22 +00:00
|
|
|
#include "gps_acq_assist.h"
|
2016-09-29 17:46:27 +00:00
|
|
|
#include <gflags/gflags.h>
|
2016-09-29 16:31:22 +00:00
|
|
|
#include <glog/logging.h>
|
2016-09-29 17:46:27 +00:00
|
|
|
#include <gtest/gtest.h>
|
|
|
|
|
|
|
|
|
2016-09-29 18:15:50 +00:00
|
|
|
DEFINE_int32(fs_in, 4000000, "Sampling rate, in Ms/s");
|
|
|
|
DEFINE_int32(max_measurement_duration, 90, "Maximum time waiting for a position fix, in seconds");
|
|
|
|
DEFINE_int32(num_measurements, 2, "Number of measurements");
|
2016-09-29 17:46:27 +00:00
|
|
|
DEFINE_string(device_address, "192.168.40.2", "USRP device IP address");
|
2016-09-29 18:15:50 +00:00
|
|
|
DEFINE_string(subdevice, "B:0", "USRP subdevice");
|
2016-09-29 16:31:22 +00:00
|
|
|
|
|
|
|
// For GPS NAVIGATION (L1)
|
|
|
|
concurrent_queue<Gps_Acq_Assist> global_gps_acq_assist_queue;
|
|
|
|
concurrent_map<Gps_Acq_Assist> global_gps_acq_assist_map;
|
|
|
|
|
2016-10-01 09:26:59 +00:00
|
|
|
std::vector<double> TTFF_v;
|
2016-10-01 08:25:29 +00:00
|
|
|
|
|
|
|
typedef struct {
|
2016-10-01 09:03:40 +00:00
|
|
|
long mtype;//required by sys v message
|
|
|
|
double ttff;
|
|
|
|
} ttff_msgbuf;
|
2016-10-01 08:25:29 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class TTFF_GPS_L1_CA_Test: public ::testing::Test
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
std::shared_ptr<InMemoryConfiguration> config;
|
|
|
|
//std::thread receive_msg_thread(receive_msg);
|
|
|
|
//void receive_msg();
|
|
|
|
};
|
|
|
|
|
|
|
|
void receive_msg()
|
|
|
|
{
|
|
|
|
ttff_msgbuf msg;
|
2016-10-01 09:26:59 +00:00
|
|
|
double ttff_msg = 0.0;
|
|
|
|
int msgrcv_size = sizeof(msg.ttff);
|
2016-10-01 08:25:29 +00:00
|
|
|
int msqid;
|
2016-10-01 09:26:59 +00:00
|
|
|
key_t key = 1101;
|
2016-10-01 08:25:29 +00:00
|
|
|
while((msqid = msgget(key, 0644)) == -1){}
|
2016-10-01 09:03:40 +00:00
|
|
|
// if ((msqid = msgget(key, 0644)) == -1) { /* connect to the queue */
|
|
|
|
// perror("TTFF MSG QUEUE NOT AVAILABLE");
|
|
|
|
// exit(1);
|
|
|
|
// }
|
2016-10-01 08:25:29 +00:00
|
|
|
|
2016-10-01 09:03:40 +00:00
|
|
|
// msqid = msgget(key, 0644);
|
2016-10-01 08:25:29 +00:00
|
|
|
//while (keep_capturing==1) {
|
|
|
|
|
2016-10-01 09:03:40 +00:00
|
|
|
if (msgrcv(msqid, &msg, msgrcv_size, 1, 0) != -1)
|
2016-10-01 08:25:29 +00:00
|
|
|
{
|
|
|
|
//jammer=msg.jammer_msg;
|
|
|
|
ttff_msg = msg.ttff;
|
|
|
|
std::cout << "-----RECEIVED! " << ttff_msg << std::endl;
|
|
|
|
//struct tm tstruct;
|
|
|
|
//char buf[80];
|
|
|
|
//tstruct = *localtime(&jammer.timestamp);
|
|
|
|
//strftime(buf, sizeof(buf), "%d-%m-%Y-%H-%M-%S", &tstruct);
|
2016-10-01 09:26:59 +00:00
|
|
|
if( ttff_msg != 0)
|
|
|
|
{
|
2016-10-01 09:39:04 +00:00
|
|
|
TTFF_v.push_back(ttff_msg / (100 * 10)); // Fix this ! averaging_depth * output_rate_ms
|
|
|
|
receive_msg();
|
2016-10-01 09:26:59 +00:00
|
|
|
}
|
2016-10-01 08:25:29 +00:00
|
|
|
//if(TTFF==0) receive_msg();
|
|
|
|
}
|
|
|
|
|
|
|
|
//}
|
2016-10-01 09:39:04 +00:00
|
|
|
|
2016-10-01 09:03:40 +00:00
|
|
|
std::cout << "--------RECEIVEr msg thread stops " << std::endl;
|
2016-10-01 08:25:29 +00:00
|
|
|
//std::cout<<"RECEIVER MSG THREAD STOP.\n";
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2016-09-29 16:31:22 +00:00
|
|
|
|
2016-09-29 20:04:53 +00:00
|
|
|
TEST(TTFF_GPS_L1_CA_Test, ColdStart)
|
2016-09-29 16:31:22 +00:00
|
|
|
{
|
2016-09-29 20:04:53 +00:00
|
|
|
std::shared_ptr<InMemoryConfiguration> config;
|
2016-10-01 08:25:29 +00:00
|
|
|
std::shared_ptr<FileConfiguration> config2;
|
2016-09-29 16:31:22 +00:00
|
|
|
unsigned int num_measurements = 0;
|
|
|
|
unsigned int num_valid_measurements = 0;
|
|
|
|
config = std::make_shared<InMemoryConfiguration>();
|
2016-10-01 08:25:29 +00:00
|
|
|
std::string path = std::string(TEST_PATH);
|
|
|
|
std::string filename = path + "../../conf/gnss-sdr_GPS_L1_USRP_X300_realtime.conf";
|
|
|
|
config2 = std::make_shared<FileConfiguration>(filename);
|
|
|
|
config2->set_property("SignalSource.samples", std::to_string(FLAGS_fs_in * FLAGS_max_measurement_duration));
|
|
|
|
|
2016-09-29 20:04:53 +00:00
|
|
|
//google::InitGoogleLogging("ttff");
|
2016-09-29 16:31:22 +00:00
|
|
|
|
|
|
|
// Set the Signal Source
|
2016-09-29 17:46:27 +00:00
|
|
|
config->set_property("GNSS-SDR.internal_fs_hz", std::to_string(FLAGS_fs_in));
|
2016-09-29 17:06:17 +00:00
|
|
|
config->set_property("SignalSource.item_type", "cshort");
|
2016-09-29 16:31:22 +00:00
|
|
|
config->set_property("SignalSource.implementation", "UHD_Signal_Source");
|
|
|
|
config->set_property("SignalSource.freq", std::to_string(1575420000));
|
2016-09-29 20:28:22 +00:00
|
|
|
config->set_property("SignalSource.sampling_frequency", std::to_string(FLAGS_fs_in));
|
2016-09-29 16:31:22 +00:00
|
|
|
config->set_property("SignalSource.gain", std::to_string(40));
|
2016-09-29 17:46:27 +00:00
|
|
|
config->set_property("SignalSource.subdevice", FLAGS_subdevice);
|
2016-09-29 18:15:50 +00:00
|
|
|
config->set_property("SignalSource.samples", std::to_string(FLAGS_fs_in * FLAGS_max_measurement_duration));
|
2016-09-29 17:46:27 +00:00
|
|
|
config->set_property("SignalSource.device_address", FLAGS_device_address);
|
2016-09-29 16:31:22 +00:00
|
|
|
|
|
|
|
// Set the Signal Conditioner
|
|
|
|
config->set_property("SignalConditioner.implementation", "Signal_Conditioner");
|
|
|
|
config->set_property("DataTypeAdapter.implementation", "Pass_Through");
|
|
|
|
config->set_property("DataTypeAdapter.item_type", "cshort");
|
|
|
|
config->set_property("InputFilter.implementation", "Fir_Filter");
|
|
|
|
config->set_property("InputFilter.dump", "false");
|
|
|
|
config->set_property("InputFilter.input_item_type", "cshort");
|
|
|
|
config->set_property("InputFilter.output_item_type", "gr_complex");
|
|
|
|
config->set_property("InputFilter.taps_item_type", "float");
|
|
|
|
config->set_property("InputFilter.number_of_taps", std::to_string(11));
|
|
|
|
config->set_property("InputFilter.number_of_bands", std::to_string(2));
|
|
|
|
config->set_property("InputFilter.band1_begin", std::to_string(0.0));
|
|
|
|
config->set_property("InputFilter.band1_end", std::to_string(0.48));
|
|
|
|
config->set_property("InputFilter.band2_begin", std::to_string(0.52));
|
|
|
|
config->set_property("InputFilter.band2_end", std::to_string(1.0));
|
|
|
|
config->set_property("InputFilter.ampl1_begin", std::to_string(1.0));
|
|
|
|
config->set_property("InputFilter.ampl1_end", std::to_string(1.0));
|
|
|
|
config->set_property("InputFilter.ampl2_begin", std::to_string(0.0));
|
|
|
|
config->set_property("InputFilter.ampl2_end", std::to_string(0.0));
|
|
|
|
config->set_property("InputFilter.band1_error", std::to_string(1.0));
|
|
|
|
config->set_property("InputFilter.band2_error", std::to_string(1.0));
|
|
|
|
config->set_property("InputFilter.filter_type", "bandpass");
|
|
|
|
config->set_property("InputFilter.grid_density", std::to_string(16));
|
2016-10-01 09:03:40 +00:00
|
|
|
config->set_property("InputFilter.sampling_frequency", std::to_string(FLAGS_fs_in));
|
2016-09-29 16:31:22 +00:00
|
|
|
config->set_property("InputFilter.IF", std::to_string(0));
|
|
|
|
config->set_property("Resampler.implementation", "Pass_Through");
|
|
|
|
config->set_property("Resampler.dump", "false");
|
|
|
|
config->set_property("Resampler.item_type", "gr_complex");
|
2016-10-01 09:03:40 +00:00
|
|
|
config->set_property("Resampler.sample_freq_in", std::to_string(FLAGS_fs_in));
|
|
|
|
config->set_property("Resampler.sample_freq_out", std::to_string(FLAGS_fs_in));
|
2016-09-29 16:31:22 +00:00
|
|
|
|
|
|
|
// Set the number of Channels
|
|
|
|
config->set_property("Channels_1C.count", std::to_string(8));
|
|
|
|
config->set_property("Channels.in_acquisition", std::to_string(1));
|
|
|
|
config->set_property("Channel.signal", "1C");
|
|
|
|
|
|
|
|
// Set Acquisition
|
2016-09-29 20:18:21 +00:00
|
|
|
config->set_property("Acquisition_1C.implementation", "GPS_L1_CA_PCPS_Tong_Acquisition");
|
2016-09-29 16:31:22 +00:00
|
|
|
config->set_property("Acquisition_1C.item_type", "gr_complex");
|
|
|
|
config->set_property("Acquisition_1C.if", std::to_string(0));
|
|
|
|
config->set_property("Acquisition_1C.coherent_integration_time_ms", std::to_string(1));
|
|
|
|
config->set_property("Acquisition_1C.threshold", std::to_string(0.01));
|
|
|
|
config->set_property("Acquisition_1C.doppler_max", std::to_string(8000));
|
|
|
|
config->set_property("Acquisition_1C.doppler_step", std::to_string(500));
|
2016-09-29 20:28:22 +00:00
|
|
|
config->set_property("Acquisition_1C.bit_transition_flag", "false");
|
2016-09-29 16:31:22 +00:00
|
|
|
config->set_property("Acquisition_1C.max_dwells", std::to_string(1));
|
2016-09-29 20:18:21 +00:00
|
|
|
config->set_property("Acquisition_1C.tong_init_val", std::to_string(2));
|
|
|
|
config->set_property("Acquisition_1C.tong_max_val", std::to_string(10));
|
|
|
|
config->set_property("Acquisition_1C.tong_max_dwells", std::to_string(30));
|
2016-09-29 16:31:22 +00:00
|
|
|
|
|
|
|
// Set Tracking
|
|
|
|
config->set_property("Tracking_1C.implementation", "GPS_L1_CA_DLL_PLL_Tracking");
|
|
|
|
config->set_property("Tracking_1C.item_type", "gr_complex");
|
|
|
|
config->set_property("Tracking_1C.if", std::to_string(0));
|
|
|
|
config->set_property("Tracking_1C.dump", "false");
|
|
|
|
config->set_property("Tracking_1C.dump_filename", "./tracking_ch_");
|
|
|
|
config->set_property("Tracking_1C.pll_bw_hz", std::to_string(30.0));
|
|
|
|
config->set_property("Tracking_1C.dll_bw_hz", std::to_string(4.0));
|
|
|
|
config->set_property("Tracking_1C.order", std::to_string(3));
|
|
|
|
config->set_property("Tracking_1C.early_late_space_chips", std::to_string(0.5));
|
|
|
|
|
|
|
|
// Set Telemetry
|
|
|
|
config->set_property("TelemetryDecoder_1C.implementation", "GPS_L1_CA_Telemetry_Decoder");
|
|
|
|
config->set_property("TelemetryDecoder_1C.dump", "false");
|
|
|
|
config->set_property("TelemetryDecoder_1C.decimation_factor", std::to_string(1));
|
|
|
|
|
|
|
|
// Set Observables
|
|
|
|
config->set_property("Observables.implementation", "GPS_L1_CA_Observables");
|
|
|
|
config->set_property("Observables.dump", "false");
|
|
|
|
config->set_property("Observables.dump_filename", "./observables.dat");
|
|
|
|
|
|
|
|
// Set PVT
|
|
|
|
config->set_property("PVT.implementation", "GPS_L1_CA_PVT");
|
|
|
|
config->set_property("PVT.averaging_depth", std::to_string(10));
|
|
|
|
config->set_property("PVT.flag_averaging", "true");
|
|
|
|
config->set_property("PVT.output_rate_ms", std::to_string(100));
|
|
|
|
config->set_property("PVT.display_rate_ms", std::to_string(500));
|
|
|
|
config->set_property("PVT.dump_filename", "./PVT");
|
|
|
|
config->set_property("PVT.nmea_dump_filename", "./gnss_sdr_pvt.nmea");
|
|
|
|
config->set_property("PVT.flag_nmea_tty_port", "false");
|
|
|
|
config->set_property("PVT.nmea_dump_devname", "/dev/pts/4");
|
|
|
|
config->set_property("PVT.flag_rtcm_server", "false");
|
|
|
|
config->set_property("PVT.flag_rtcm_tty_port", "false");
|
|
|
|
config->set_property("PVT.rtcm_dump_devname", "/dev/pts/1");
|
|
|
|
config->set_property("PVT.dump", "false");
|
|
|
|
|
|
|
|
|
2016-09-29 17:06:17 +00:00
|
|
|
bool valid_pvt_received = false;
|
2016-10-01 08:25:29 +00:00
|
|
|
//std::thread receive_msg_thread(receive_msg);
|
|
|
|
|
2016-09-29 17:06:17 +00:00
|
|
|
|
2016-09-29 18:15:50 +00:00
|
|
|
int n;
|
|
|
|
for(n = 0; n < FLAGS_num_measurements; n++) //
|
2016-09-29 17:06:17 +00:00
|
|
|
{
|
2016-10-01 08:25:29 +00:00
|
|
|
|
2016-09-29 17:06:17 +00:00
|
|
|
// reset start( hot /warm / cold )
|
|
|
|
// COLD START
|
|
|
|
config->set_property("GNSS-SDR.SUPL_gps_enabled", "false");
|
|
|
|
config->set_property("GNSS-SDR.SUPL_read_gps_assistance_xml", "false");
|
2016-10-01 08:25:29 +00:00
|
|
|
config2->set_property("GNSS-SDR.SUPL_read_gps_assistance_xml", "false");
|
2016-09-29 17:06:17 +00:00
|
|
|
|
2016-10-01 08:25:29 +00:00
|
|
|
|
|
|
|
std::shared_ptr<ControlThread> control_thread = std::make_shared<ControlThread>(config2);
|
2016-09-29 17:06:17 +00:00
|
|
|
|
2016-09-29 17:46:27 +00:00
|
|
|
// - start clock
|
2016-09-29 18:15:50 +00:00
|
|
|
// record startup time
|
|
|
|
struct timeval tv;
|
|
|
|
gettimeofday(&tv, NULL);
|
|
|
|
long long int begin = tv.tv_sec * 1000000 + tv.tv_usec;
|
|
|
|
|
2016-09-29 17:46:27 +00:00
|
|
|
// - start receiver
|
2016-09-29 17:06:17 +00:00
|
|
|
try
|
|
|
|
{
|
|
|
|
control_thread->run();
|
|
|
|
}
|
|
|
|
catch( boost::exception & e )
|
|
|
|
{
|
|
|
|
std::cout << "Boost exception: " << boost::diagnostic_information(e);
|
|
|
|
}
|
|
|
|
catch(std::exception const& ex)
|
|
|
|
{
|
|
|
|
std::cout << "STD exception: " << ex.what();
|
|
|
|
}
|
|
|
|
|
|
|
|
// - if (pvt_fix | max_waiting_time)
|
|
|
|
// - stop_clock
|
2016-09-29 18:15:50 +00:00
|
|
|
gettimeofday(&tv, NULL);
|
|
|
|
long long int end = tv.tv_sec * 1000000 + tv.tv_usec;
|
|
|
|
double ttff = static_cast<double>(end - begin) / 1000000.0;
|
|
|
|
|
|
|
|
std::shared_ptr<GNSSFlowgraph> flowgraph = control_thread->flowgraph();
|
|
|
|
EXPECT_FALSE(flowgraph->running());
|
2016-10-01 08:25:29 +00:00
|
|
|
|
|
|
|
|
2016-09-29 17:06:17 +00:00
|
|
|
num_measurements = num_measurements + 1;
|
2016-09-29 18:15:50 +00:00
|
|
|
std::cout << "Measurement " << num_measurements << ", which took " << ttff << " seconds." << std::endl;
|
2016-09-29 17:46:27 +00:00
|
|
|
std::this_thread::sleep_until(std::chrono::system_clock::now() + std::chrono::seconds(5));
|
2016-09-29 17:06:17 +00:00
|
|
|
// if (pvt_fix) num_valid_measurements = num_valid_measurements + 1;
|
|
|
|
}
|
2016-09-29 16:31:22 +00:00
|
|
|
std::cout << "BYE " << num_measurements << std::endl;
|
2016-09-29 17:06:17 +00:00
|
|
|
// Compute min, max, mean, stdev,
|
2016-10-01 09:03:40 +00:00
|
|
|
//receive_msg_thread.join();
|
2016-09-29 17:06:17 +00:00
|
|
|
// Print TTFF report
|
2016-09-29 16:31:22 +00:00
|
|
|
|
|
|
|
}
|
2016-09-29 20:04:53 +00:00
|
|
|
|
|
|
|
|
|
|
|
int main(int argc, char **argv)
|
|
|
|
{
|
|
|
|
std::cout << "Running Time-To-First-Fix test..." << std::endl;
|
|
|
|
int res = 0;
|
2016-10-01 09:26:59 +00:00
|
|
|
TTFF_v.clear();
|
2016-09-29 20:04:53 +00:00
|
|
|
testing::InitGoogleTest(&argc, argv);
|
|
|
|
google::ParseCommandLineFlags(&argc, &argv, true);
|
|
|
|
google::InitGoogleLogging(argv[0]);
|
2016-10-01 08:25:29 +00:00
|
|
|
//Create Sys V message queue
|
|
|
|
key_t sysv_msg_key;
|
2016-10-01 09:03:40 +00:00
|
|
|
int sysv_msqid;
|
2016-10-01 09:26:59 +00:00
|
|
|
sysv_msg_key = 1101;
|
2016-10-01 09:03:40 +00:00
|
|
|
int msgflg = IPC_CREAT | 0666;
|
|
|
|
if ((sysv_msqid = msgget(sysv_msg_key, msgflg )) == -1){}
|
|
|
|
//{
|
2016-10-01 09:26:59 +00:00
|
|
|
// std::cout<<"GNSS-SDR can not create message queues!\n";
|
2016-10-01 09:03:40 +00:00
|
|
|
// perror("msgget");
|
|
|
|
// throw new std::exception();
|
|
|
|
//}
|
2016-10-01 09:26:59 +00:00
|
|
|
|
2016-10-01 08:25:29 +00:00
|
|
|
std::thread receive_msg_thread(receive_msg);
|
2016-09-29 20:04:53 +00:00
|
|
|
try
|
|
|
|
{
|
|
|
|
res = RUN_ALL_TESTS();
|
|
|
|
}
|
|
|
|
catch(...)
|
|
|
|
{
|
|
|
|
LOG(WARNING) << "Unexpected catch";
|
|
|
|
}
|
2016-10-01 08:25:29 +00:00
|
|
|
ttff_msgbuf msg;
|
|
|
|
msg.mtype = 1;
|
2016-10-01 09:26:59 +00:00
|
|
|
msg.ttff = 0;
|
2016-10-01 08:25:29 +00:00
|
|
|
int msgsend_size;
|
2016-10-01 09:26:59 +00:00
|
|
|
msgsend_size = sizeof(msg.ttff);
|
2016-10-01 08:25:29 +00:00
|
|
|
msgsnd(sysv_msqid, &msg, msgsend_size, IPC_NOWAIT);
|
|
|
|
receive_msg_thread.join();
|
2016-10-01 09:26:59 +00:00
|
|
|
std::cout << "-------------------TTFF:" << std::accumulate(TTFF_v.begin(), TTFF_v.end(), 0.0) / TTFF_v.size() << std::endl;
|
2016-09-29 20:04:53 +00:00
|
|
|
google::ShutDownCommandLineFlags();
|
|
|
|
return res;
|
|
|
|
}
|