From 057c9feb2859edb2e0f82a3cad68bec64754dae9 Mon Sep 17 00:00:00 2001 From: Pietro Incardona <incardon@mpi-cbg.de> Date: Sun, 3 Mar 2019 23:17:15 +0100 Subject: [PATCH] Adding test for MetaParser --- src/CMakeLists.txt | 10 +- src/MetaParser/MetaParser.hpp | 84 ++++ src/MetaParser/MetaParser_unit_test.cpp | 117 ++++++ src/VTKWriter/VTKWriter_point_set.hpp | 35 ++ src/VTKWriter/VTKWriter_unit_tests.hpp | 24 +- test_data/vtk_points_pp_header_test.vtk | 515 ++++++++++++++++++++++++ 6 files changed, 779 insertions(+), 6 deletions(-) create mode 100644 src/MetaParser/MetaParser.hpp create mode 100644 src/MetaParser/MetaParser_unit_test.cpp create mode 100644 test_data/vtk_points_pp_header_test.vtk diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index f85338b6..b1c34e80 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -2,7 +2,15 @@ cmake_minimum_required(VERSION 3.8 FATAL_ERROR) ########################### Executables -add_executable(io main.cpp HDF5_wr/HDF5_writer_cuda.cu ObjReader/ObjReader_unit_test.cpp ../../openfpm_vcluster/src/VCluster/VCluster.cpp ../../openfpm_devices/src/memory/CudaMemory.cu ../../openfpm_devices/src/memory/HeapMemory.cpp ../../openfpm_devices/src/Memleak_check.cpp ../../openfpm_devices/src/memory/PtrMemory.cpp) +add_executable(io main.cpp + MetaParser/MetaParser_unit_test.cpp + HDF5_wr/HDF5_writer_cuda.cu + ObjReader/ObjReader_unit_test.cpp + ../../openfpm_vcluster/src/VCluster/VCluster.cpp + ../../openfpm_devices/src/memory/CudaMemory.cu + ../../openfpm_devices/src/memory/HeapMemory.cpp + ../../openfpm_devices/src/Memleak_check.cpp + ../../openfpm_devices/src/memory/PtrMemory.cpp) if ( CMAKE_COMPILER_IS_GNUCC ) target_compile_options(io PRIVATE "-Wno-deprecated-declarations") diff --git a/src/MetaParser/MetaParser.hpp b/src/MetaParser/MetaParser.hpp new file mode 100644 index 00000000..7481b740 --- /dev/null +++ b/src/MetaParser/MetaParser.hpp @@ -0,0 +1,84 @@ +/* + * MetaParser.hpp + * + * Created on: Mar 3, 2019 + * Author: i-bird + */ + +#ifndef METAPARSER_HPP_ +#define METAPARSER_HPP_ + +#include <algorithm> +#include <iostream> +#include <iterator> +#include <string> +#include <vector> + +#include <boost/bind.hpp> +#include <boost/program_options.hpp> +#include <boost/tokenizer.hpp> + +typedef boost::program_options::options_description MetaParser_options; +namespace MetaParser_def = boost::program_options; + +class MetaParser +{ + boost::program_options::options_description desc; + + boost::program_options::variables_map vm; + +public: + + MetaParser(boost::program_options::options_description & desc) + :desc(desc) + { + } + + /*! \brief Parse the string of options + * + * \param string of options + * + */ + bool parse(std::string & opts) + { + std::istringstream iss(opts); + + // Parse mocked up input. + boost::program_options::store(boost::program_options::parse_config_file(iss,desc), vm); + boost::program_options::notify(vm); + + return true; + } + + /*! \brief Return the option opt in value + * + * \param opt option to check + * \param value where to store the value of the option + * + * \return true if the option has been set + * + */ + template<typename T> + bool getOption(std::string opt,T & value) + { + if (vm.count(opt)) + { + value = vm[opt].as<T>(); + return true; + } + + return false; + } + + /*! \brief clear everything you parsed so far + * + * + */ + void clear() + { + vm.clear(); + } +}; + + +#endif /* METAPARSER_HPP_ */ diff --git a/src/MetaParser/MetaParser_unit_test.cpp b/src/MetaParser/MetaParser_unit_test.cpp new file mode 100644 index 00000000..a02a9c2d --- /dev/null +++ b/src/MetaParser/MetaParser_unit_test.cpp @@ -0,0 +1,117 @@ +/* + * MetaParser_unit_test.cpp + * + * Created on: Mar 3, 2019 + * Author: i-bird + */ + +#define BOOST_TEST_DYN_LINK +#include <boost/test/unit_test.hpp> + +#include "MetaParser.hpp" + +BOOST_AUTO_TEST_SUITE( vtk_writer_tests ) + +BOOST_AUTO_TEST_CASE( vtk_writer_meta_parser_use ) +{ + std::string test_options("time = 5.0"); + std::string test_options2("time=6.0"); + std::string test_options3("time =7.0"); + std::string test_options4("time= 8.0"); + std::string test_options5("time= 9.0"); + + double time = 1.0; + + MetaParser_options opts; + opts.add_options() + ("time", MetaParser_def::value<double>(&time)); + + MetaParser mp(opts); + mp.parse(test_options); + + BOOST_REQUIRE_EQUAL(time,5.0); + + time = 0.0; + bool exist = mp.getOption("time",time); + + BOOST_REQUIRE_EQUAL(exist,true); + BOOST_REQUIRE_EQUAL(time,5.0); + + exist = mp.getOption("invalid",time); + BOOST_REQUIRE_EQUAL(exist,false); + + // parse another + + mp.clear(); + + time = 0.0; + mp.parse(test_options2); + + BOOST_REQUIRE_EQUAL(time,6.0); + + time = 0.0; + exist = mp.getOption("time",time); + + BOOST_REQUIRE_EQUAL(exist,true); + BOOST_REQUIRE_EQUAL(time,6.0); + + exist = mp.getOption("invalid",time); + BOOST_REQUIRE_EQUAL(exist,false); + + // parse another + + mp.clear(); + + time = 0.0; + mp.parse(test_options3); + + BOOST_REQUIRE_EQUAL(time,7.0); + + time = 0.0; + exist = mp.getOption("time",time); + + BOOST_REQUIRE_EQUAL(exist,true); + BOOST_REQUIRE_EQUAL(time,7.0); + + exist = mp.getOption("invalid",time); + BOOST_REQUIRE_EQUAL(exist,false); + + // parse another + + mp.clear(); + + time = 0.0; + mp.parse(test_options4); + + BOOST_REQUIRE_EQUAL(time,8.0); + + time = 0.0; + exist = mp.getOption("time",time); + + BOOST_REQUIRE_EQUAL(exist,true); + BOOST_REQUIRE_EQUAL(time,8.0); + + exist = mp.getOption("invalid",time); + BOOST_REQUIRE_EQUAL(exist,false); + + // parse another + + mp.clear(); + + time = 0.0; + mp.parse(test_options5); + + BOOST_REQUIRE_EQUAL(time,9.0); + + time = 0.0; + exist = mp.getOption("time",time); + + BOOST_REQUIRE_EQUAL(exist,true); + BOOST_REQUIRE_EQUAL(time,9.0); + + exist = mp.getOption("invalid",time); + BOOST_REQUIRE_EQUAL(exist,false); + +} + +BOOST_AUTO_TEST_SUITE_END() diff --git a/src/VTKWriter/VTKWriter_point_set.hpp b/src/VTKWriter/VTKWriter_point_set.hpp index ef19ca8c..ce920abd 100644 --- a/src/VTKWriter/VTKWriter_point_set.hpp +++ b/src/VTKWriter/VTKWriter_point_set.hpp @@ -14,6 +14,7 @@ #include "is_vtk_writable.hpp" #include <string> #include "byteswap_portable.hpp" +#include "MetaParser/MetaParser.hpp" /*! \brief Store a reference to the vector position * @@ -337,6 +338,37 @@ class VTKWriter<pair,VECTOR_POINTS> return v_out; } + /*! \brief return the meta data string + * + * \param meta_data string with the meta-data to add + * + */ + std::string add_meta_data(std::string & meta_data) + { + std::string meta_string; + + // check for time metadata + MetaParser_options opts; + opts.add_options() + ("time", MetaParser_def::value<double>()); + + MetaParser mp(opts); + mp.parse(meta_data); + + double time = 0.0; + bool exist = mp.getOption("time",time); + + if (exist == true) + { + meta_string += "FIELD FieldData 1\n"; + meta_string += "TIME 1 1 double\n"; + meta_string += std::to_string(time); + meta_string += "\n"; + } + + return meta_string; + } + public: /*! @@ -381,6 +413,7 @@ public: template<int prp = -1> bool write(std::string file, const openfpm::vector<std::string> & prop_names, std::string f_name = "points" , + std::string meta_data = "", file_type ft = file_type::ASCII) { // Header for the vtk @@ -413,6 +446,8 @@ public: // Data type for graph is DATASET POLYDATA vtk_header += "DATASET POLYDATA\n"; + vtk_header += add_meta_data(meta_data); + // point properties header point_prop_header = get_point_properties_list(ft); diff --git a/src/VTKWriter/VTKWriter_unit_tests.hpp b/src/VTKWriter/VTKWriter_unit_tests.hpp index ee7d21e5..de10b806 100644 --- a/src/VTKWriter/VTKWriter_unit_tests.hpp +++ b/src/VTKWriter/VTKWriter_unit_tests.hpp @@ -1041,6 +1041,20 @@ BOOST_AUTO_TEST_CASE( vtk_writer_use_point_set ) test = compare("vtk_points_pp.vtk","test_data/vtk_points_pp_test.vtk"); BOOST_REQUIRE_EQUAL(test,true); +#endif + + // Create a writer and write + VTKWriter<boost::mpl::pair<openfpm::vector<Point<3,double>>,openfpm::vector<aggregate<float,Point<3,float>>>>,VECTOR_POINTS> vtk_v3; + vtk_v3.add(v1ps,v4pp,75); + + vtk_v3.write("vtk_points_pp_header.vtk",prp_names,"points","time=5.123"); + +#ifndef SE_CLASS3 + + // Check that match + test = compare("vtk_points_pp_header.vtk","test_data/vtk_points_pp_header_test.vtk"); + BOOST_REQUIRE_EQUAL(test,true); + #endif } @@ -1171,8 +1185,8 @@ BOOST_AUTO_TEST_CASE( vtk_writer_use_point_set_binary ) vtk_v.add(v3ps,v3pp,90); openfpm::vector<std::string> prp_names; - vtk_v.write("vtk_points_bin.vtk",prp_names,"vtk output",file_type::BINARY); - vtk_v.write("vtk_points_bin2.vtk",prp_names,"vtk output",file_type::BINARY); + vtk_v.write("vtk_points_bin.vtk",prp_names,"vtk output","",file_type::BINARY); + vtk_v.write("vtk_points_bin2.vtk",prp_names,"vtk output","",file_type::BINARY); #ifndef SE_CLASS3 @@ -1190,7 +1204,7 @@ BOOST_AUTO_TEST_CASE( vtk_writer_use_point_set_binary ) VTKWriter<boost::mpl::pair<openfpm::vector<Point<3,double>>,openfpm::vector<aggregate<float,Point<3,float>>>>,VECTOR_POINTS> vtk_v2; vtk_v2.add(v1ps,v4pp,75); - vtk_v2.write("vtk_points_pp_bin.vtk",prp_names,"vtk output",file_type::BINARY); + vtk_v2.write("vtk_points_pp_bin.vtk",prp_names,"vtk output","",file_type::BINARY); #ifndef SE_CLASS3 @@ -1286,7 +1300,7 @@ BOOST_AUTO_TEST_CASE( vtk_writer_use_point_set_binary ) openfpm::vector<std::string> stub; - vtk_v.write("vtk_points_2d_bin.vtk",stub,"vtk output",file_type::BINARY); + vtk_v.write("vtk_points_2d_bin.vtk",stub,"vtk output","",file_type::BINARY); #ifndef SE_CLASS3 @@ -1302,7 +1316,7 @@ BOOST_AUTO_TEST_CASE( vtk_writer_use_point_set_binary ) VTKWriter<boost::mpl::pair<openfpm::vector<Point<2,double>>,openfpm::vector<aggregate<float[3],double[2]>>>,VECTOR_POINTS> vtk_v2; vtk_v2.add(v1ps,v4pp,75); - vtk_v2.write("vtk_points_2d_pp_bin.vtk",stub,"vtk output",file_type::BINARY); + vtk_v2.write("vtk_points_2d_pp_bin.vtk",stub,"vtk output","",file_type::BINARY); #ifndef SE_CLASS3 diff --git a/test_data/vtk_points_pp_header_test.vtk b/test_data/vtk_points_pp_header_test.vtk new file mode 100644 index 00000000..7cb8f121 --- /dev/null +++ b/test_data/vtk_points_pp_header_test.vtk @@ -0,0 +1,515 @@ +# vtk DataFile Version 3.0 +points +ASCII +DATASET POLYDATA +FIELD FieldData 1 +TIME 1 1 double +5.123000 +POINTS 100 float +0.191120 0.542772 0.939108 +0.933523 0.710147 0.682257 +0.228446 0.513097 0.438905 +0.700754 0.436179 0.434735 +0.751419 0.522504 0.196855 +0.666369 0.261523 0.050127 +0.573708 0.768383 0.022587 +0.750211 0.313137 0.190846 +0.507718 0.273360 0.264172 +0.670213 0.932599 0.212948 +0.586036 0.006718 0.574775 +0.336361 0.205412 0.440432 +0.553825 0.740555 0.064820 +0.764503 0.468990 0.878126 +0.323438 0.181610 0.943831 +0.329992 0.043079 0.688576 +0.095793 0.009830 0.801123 +0.349360 0.212307 0.266992 +0.368002 0.414173 0.890974 +0.471037 0.198481 0.584590 +0.363141 0.971788 0.567570 +0.193627 0.047362 0.347666 +0.078823 0.824102 0.303324 +0.892978 0.147594 0.589520 +0.768770 0.021556 0.879563 +0.173734 0.131239 0.179741 +0.392798 0.563805 0.325374 +0.241990 0.120892 0.993650 +0.950192 0.297734 0.372967 +0.618250 0.020735 0.852418 +0.507541 0.634685 0.435244 +0.857826 0.812930 0.263612 +0.905927 0.426169 0.242918 +0.551551 0.826687 0.394286 +0.107476 0.018033 0.122876 +0.027658 0.315680 0.861391 +0.864926 0.042390 0.667640 +0.937087 0.686836 0.209923 +0.960032 0.214003 0.456393 +0.838234 0.705078 0.379994 +0.743514 0.670946 0.671558 +0.434425 0.879627 0.032296 +0.954834 0.877288 0.061284 +0.239914 0.979709 0.690876 +0.334337 0.292961 0.194138 +0.397971 0.064623 0.159310 +0.639743 0.559217 0.628284 +0.319393 0.698422 0.808751 +0.534981 0.605794 0.215716 +0.932453 0.633508 0.954549 +0.860046 0.170877 0.901505 +0.581338 0.696935 0.013719 +0.273513 0.037100 0.801600 +0.857205 0.467507 0.627542 +0.752721 0.974119 0.427029 +0.371101 0.245019 0.119228 +0.733240 0.911167 0.240259 +0.659184 0.906727 0.920069 +0.723200 0.826380 0.620956 +0.665010 0.286470 0.644219 +0.550957 0.831365 0.249487 +0.136109 0.843937 0.995786 +0.958540 0.434625 0.812213 +0.025767 0.297417 0.212592 +0.956965 0.060432 0.382506 +0.647490 0.425935 0.083679 +0.492244 0.694858 0.917290 +0.595547 0.101746 0.165874 +0.715210 0.552892 0.556047 +0.727179 0.190203 0.479701 +0.452899 0.191989 0.800239 +0.189775 0.575804 0.255534 +0.787141 0.426864 0.467209 +0.674216 0.630124 0.240190 +0.921028 0.344758 0.550895 +0.051571 0.205424 0.679874 +0.450943 0.397533 0.256193 +0.520349 0.229449 0.854270 +0.444768 0.451041 0.509270 +0.033064 0.374076 0.800554 +0.524198 0.393980 0.552048 +0.743037 0.632495 0.584216 +0.264430 0.570424 0.532054 +0.538226 0.023322 0.450331 +0.513191 0.768138 0.952403 +0.790408 0.301653 0.043437 +0.328417 0.622360 0.766373 +0.186272 0.564519 0.339561 +0.251027 0.787802 0.694365 +0.045131 0.074015 0.734981 +0.066324 0.363983 0.337433 +0.129496 0.763412 0.395678 +0.451936 0.568539 0.719855 +0.084249 0.651408 0.904191 +0.484451 0.939076 0.217938 +0.355350 0.994250 0.900963 +0.195476 0.033896 0.116821 +0.772962 0.692030 0.614234 +0.727780 0.125820 0.608612 +0.602774 0.518449 0.155444 +VERTICES 100 200 +1 0 +1 1 +1 2 +1 3 +1 4 +1 5 +1 6 +1 7 +1 8 +1 9 +1 10 +1 11 +1 12 +1 13 +1 14 +1 15 +1 16 +1 17 +1 18 +1 19 +1 20 +1 21 +1 22 +1 23 +1 24 +1 25 +1 26 +1 27 +1 28 +1 29 +1 30 +1 31 +1 32 +1 33 +1 34 +1 35 +1 36 +1 37 +1 38 +1 39 +1 40 +1 41 +1 42 +1 43 +1 44 +1 45 +1 46 +1 47 +1 48 +1 49 +1 50 +1 51 +1 52 +1 53 +1 54 +1 55 +1 56 +1 57 +1 58 +1 59 +1 60 +1 61 +1 62 +1 63 +1 64 +1 65 +1 66 +1 67 +1 68 +1 69 +1 70 +1 71 +1 72 +1 73 +1 74 +1 75 +1 76 +1 77 +1 78 +1 79 +1 80 +1 81 +1 82 +1 83 +1 84 +1 85 +1 86 +1 87 +1 88 +1 89 +1 90 +1 91 +1 92 +1 93 +1 94 +1 95 +1 96 +1 97 +1 98 +1 99 +POINT_DATA 100 +SCALARS attr0 float +LOOKUP_TABLE default +0.949426 +0.277201 +0.376442 +0.502502 +0.661436 +0.805367 +0.342563 +0.811196 +0.865707 +0.528286 +0.214237 +0.222135 +0.680595 +0.877432 +0.498441 +0.960167 +0.530659 +0.365743 +0.515093 +0.804031 +0.680893 +0.127910 +0.717390 +0.977225 +0.272178 +0.926172 +0.580568 +0.321983 +0.497249 +0.938873 +0.833009 +0.779967 +0.725488 +0.199308 +0.090781 +0.817653 +0.191807 +0.906924 +0.864567 +0.695952 +0.682480 +0.979791 +0.491532 +0.533063 +0.083141 +0.247945 +0.335915 +0.026614 +0.983773 +0.523158 +0.739292 +0.914939 +0.454955 +0.820094 +0.286058 +0.676279 +0.070532 +0.776539 +0.591060 +0.998482 +0.735711 +0.560975 +0.015887 +0.152219 +0.998366 +0.840241 +0.050251 +0.069199 +0.564634 +0.496885 +0.432840 +0.867086 +0.502347 +0.079045 +0.546933 +0.338569 +0.220038 +0.319801 +0.672418 +0.929235 +0.530605 +0.678448 +0.264949 +0.141648 +0.999292 +0.607647 +0.625696 +0.259787 +0.659342 +0.527433 +0.300028 +0.472939 +0.718906 +0.312510 +0.047817 +0.659605 +0.295081 +0.876629 +0.954925 +0.118496 +VECTORS attr1 float +0.657156 0.682034 0.025183 +0.250088 0.607234 0.263825 +0.739673 0.039018 0.114608 +0.194670 0.401742 0.475700 +0.413817 0.294766 0.681465 +0.015654 0.653189 0.103735 +0.009091 0.688525 0.315795 +0.667080 0.032995 0.262446 +0.434889 0.179694 0.042175 +0.758505 0.171335 0.646745 +0.964508 0.447138 0.034446 +0.747196 0.863964 0.978880 +0.625662 0.475677 0.615332 +0.092992 0.950583 0.672225 +0.026450 0.304725 0.674599 +0.668662 0.198033 0.349307 +0.511365 0.736590 0.331228 +0.214901 0.920647 0.302787 +0.624194 0.193248 0.903050 +0.732847 0.734187 0.774465 +0.122126 0.636064 0.978777 +0.633133 0.172681 0.296620 +0.137659 0.404177 0.315169 +0.421794 0.706947 0.824835 +0.777115 0.369309 0.959553 +0.182539 0.907493 0.264560 +0.612276 0.923360 0.322679 +0.239125 0.906687 0.812745 +0.799694 0.244892 0.122680 +0.694895 0.871504 0.184096 +0.632809 0.933001 0.947730 +0.478003 0.610656 0.558196 +0.530773 0.175834 0.618853 +0.141485 0.444245 0.747305 +0.002605 0.422395 0.095072 +0.873376 0.003198 0.554611 +0.039373 0.473211 0.087016 +0.986558 0.508914 0.051935 +0.569195 0.091257 0.297895 +0.504004 0.034606 0.582476 +0.883971 0.690371 0.125719 +0.709503 0.007746 0.349253 +0.354675 0.285570 0.821368 +0.649714 0.380471 0.658330 +0.240403 0.304495 0.841470 +0.060240 0.425689 0.573951 +0.082922 0.593872 0.293519 +0.664300 0.935124 0.505412 +0.593555 0.934290 0.449730 +0.233373 0.680789 0.471149 +0.123419 0.541032 0.943018 +0.840163 0.005624 0.588636 +0.054774 0.643167 0.612905 +0.825145 0.677922 0.317877 +0.082006 0.561248 0.378754 +0.052267 0.955961 0.847171 +0.732659 0.672963 0.470395 +0.108920 0.168110 0.834694 +0.754526 0.407000 0.304273 +0.158420 0.244210 0.368963 +0.787678 0.950612 0.241943 +0.298357 0.024632 0.268835 +0.878477 0.185988 0.213471 +0.066472 0.649750 0.886616 +0.737895 0.382408 0.894947 +0.011884 0.751527 0.573463 +0.952056 0.403111 0.874667 +0.131470 0.252003 0.567192 +0.544668 0.750556 0.258386 +0.119451 0.395768 0.793354 +0.797257 0.862283 0.085578 +0.899564 0.510865 0.487300 +0.474531 0.325321 0.350061 +0.878789 0.043523 0.356339 +0.642490 0.645894 0.389727 +0.904003 0.108312 0.849800 +0.174632 0.494240 0.010674 +0.896802 0.164147 0.994820 +0.275338 0.486372 0.320905 +0.717285 0.101265 0.393299 +0.499842 0.160009 0.718023 +0.802297 0.769054 0.496464 +0.075878 0.302394 0.821459 +0.251684 0.943570 0.225473 +0.478271 0.031636 0.955801 +0.763669 0.821611 0.789073 +0.882342 0.728198 0.556009 +0.762217 0.059642 0.539531 +0.236410 0.845215 0.047267 +0.921424 0.922028 0.936481 +0.544335 0.221366 0.746972 +0.435478 0.182577 0.211759 +0.970230 0.869358 0.825359 +0.911490 0.459484 0.970361 +0.467178 0.361457 0.782635 +0.655313 0.251648 0.939518 +0.194075 0.629709 0.323444 +0.520398 0.954876 0.669206 +0.768459 0.303060 0.968093 +0.995774 0.780706 0.013757 +SCALARS domain float +LOOKUP_TABLE default +1.0 +1.0 +1.0 +1.0 +1.0 +1.0 +1.0 +1.0 +1.0 +1.0 +1.0 +1.0 +1.0 +1.0 +1.0 +1.0 +1.0 +1.0 +1.0 +1.0 +1.0 +1.0 +1.0 +1.0 +1.0 +1.0 +1.0 +1.0 +1.0 +1.0 +1.0 +1.0 +1.0 +1.0 +1.0 +1.0 +1.0 +1.0 +1.0 +1.0 +1.0 +1.0 +1.0 +1.0 +1.0 +1.0 +1.0 +1.0 +1.0 +1.0 +1.0 +1.0 +1.0 +1.0 +1.0 +1.0 +1.0 +1.0 +1.0 +1.0 +1.0 +1.0 +1.0 +1.0 +1.0 +1.0 +1.0 +1.0 +1.0 +1.0 +1.0 +1.0 +1.0 +1.0 +1.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 -- GitLab