Hello community, here is the log from the commit of package libyui for openSUSE:Factory checked in at 2018-08-02 14:55:52 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/libyui (Old) and /work/SRC/openSUSE:Factory/.libyui.new (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "libyui" Thu Aug 2 14:55:52 2018 rev:35 rq:626654 version:3.4.2 Changes: -------- --- /work/SRC/openSUSE:Factory/libyui/libyui.changes 2018-05-17 19:31:52.962410950 +0200 +++ /work/SRC/openSUSE:Factory/.libyui.new/libyui.changes 2018-08-02 14:56:00.672062754 +0200 @@ -1,0 +2,8 @@ +Thu Jul 26 07:45:20 UTC 2018 - [email protected] + +- Improved the FSize class to handle arbitrary sizes, use the boost + multiprecision library instead of `long long` which overflows for + values > 8EiB (bsc#991090) +- 3.4.2 + +------------------------------------------------------------------- Old: ---- libyui-3.4.1.tar.bz2 New: ---- libyui-3.4.2.tar.bz2 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ libyui-doc.spec ++++++ --- /var/tmp/diff_new_pack.1vw1Ed/_old 2018-08-02 14:56:01.432064026 +0200 +++ /var/tmp/diff_new_pack.1vw1Ed/_new 2018-08-02 14:56:01.436064032 +0200 @@ -17,10 +17,10 @@ %define parent libyui -%define so_version 8 +%define so_version 9 Name: %{parent}-doc -Version: 3.4.1 +Version: 3.4.2 Release: 0 Source: %{parent}-%{version}.tar.bz2 ++++++ libyui.spec ++++++ --- /var/tmp/diff_new_pack.1vw1Ed/_old 2018-08-02 14:56:01.452064059 +0200 +++ /var/tmp/diff_new_pack.1vw1Ed/_new 2018-08-02 14:56:01.452064059 +0200 @@ -17,15 +17,20 @@ Name: libyui -Version: 3.4.1 +Version: 3.4.2 Release: 0 Source: %{name}-%{version}.tar.bz2 -%define so_version 8 +%define so_version 9 %define bin_name %{name}%{so_version} +# optionally build with code coverage reporting, +# this uses debug build, do not use in production! +%bcond_with coverage + %if 0%{?suse_version} > 1325 BuildRequires: libboost_headers-devel +BuildRequires: libboost_test-devel %else BuildRequires: boost-devel %endif @@ -33,6 +38,12 @@ BuildRequires: gcc-c++ BuildRequires: pkg-config +%if %{with coverage} +# normally the coverage feature should not be used out of CI +# but to be on the safe side... +BuildRequires: lcov +%endif + Url: http://github.com/libyui/ Summary: GUI-abstraction library License: LGPL-2.1 or LGPL-3.0 @@ -70,6 +81,7 @@ %if 0%{?suse_version} > 1325 Requires: libboost_headers-devel +Requires: libboost_test-devel %else Requires: boost-devel %endif @@ -99,29 +111,41 @@ %build ./bootstrap.sh - -export CFLAGS="$RPM_OPT_FLAGS -DNDEBUG $(getconf LFS_CFLAGS)" -export CXXFLAGS="$RPM_OPT_FLAGS -DNDEBUG $(getconf LFS_CFLAGS)" - mkdir build cd build +%if %{with coverage} +CMAKE_OPTS="-DCMAKE_BUILD_TYPE=DEBUG -DENABLE_CODE_COVERAGE=ON" +# the debug build type is incompatible with the default $RPM_OPT_FLAGS, +# do not use them +export CFLAGS="-DNDEBUG $(getconf LFS_CFLAGS)" +export CXXFLAGS="-DNDEBUG $(getconf LFS_CFLAGS)" +%else +export CFLAGS="$RPM_OPT_FLAGS -DNDEBUG $(getconf LFS_CFLAGS)" +export CXXFLAGS="$RPM_OPT_FLAGS -DNDEBUG $(getconf LFS_CFLAGS)" %if %{?_with_debug:1}%{!?_with_debug:0} -cmake .. \ - -DYPREFIX=%{_prefix} \ - -DDOC_DIR=%{_docdir} \ - -DLIB_DIR=%{_lib} \ - -DCMAKE_BUILD_TYPE=RELWITHDEBINFO +CMAKE_OPTS="-DCMAKE_BUILD_TYPE=RELWITHDEBINFO" %else +CMAKE_OPTS="-DCMAKE_BUILD_TYPE=RELEASE" +%endif +%endif + cmake .. \ -DYPREFIX=%{_prefix} \ -DDOC_DIR=%{_docdir} \ -DLIB_DIR=%{_lib} \ - -DCMAKE_BUILD_TYPE=RELEASE -%endif + $CMAKE_OPTS make %{?jobs:-j%jobs} +%check +cd build +make test +%if %{with coverage} +# generate code coverage data +make coverage +%endif + %install cd build make install DESTDIR="$RPM_BUILD_ROOT" ++++++ libyui-3.4.1.tar.bz2 -> libyui-3.4.2.tar.bz2 ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libyui-3.4.1/.travis.yml new/libyui-3.4.2/.travis.yml --- old/libyui-3.4.1/.travis.yml 2018-05-14 14:10:38.000000000 +0200 +++ new/libyui-3.4.2/.travis.yml 2018-07-31 09:50:54.000000000 +0200 @@ -8,4 +8,4 @@ script: # the "libyui-travis" script is included in the base libyui/devel image # see https://github.com/libyui/docker-devel/blob/master/libyui-travis - - docker run -it libyui-image libyui-travis + - docker run -it -e COVERALLS_TOKEN="$COVERALLS_TOKEN" -e TRAVIS_JOB_ID="$TRAVIS_JOB_ID" libyui-image libyui-travis diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libyui-3.4.1/Makefile.cvs new/libyui-3.4.2/Makefile.cvs --- old/libyui-3.4.1/Makefile.cvs 2018-05-14 14:10:38.000000000 +0200 +++ new/libyui-3.4.2/Makefile.cvs 2018-07-31 09:50:54.000000000 +0200 @@ -2,6 +2,11 @@ # Makefile.cvs # +# enable coverage if $COVERAGE is set to 1 +ifeq ($(COVERAGE), 1) +EXTRA_PARAMS := -DENABLE_CODE_COVERAGE=ON +endif + all: configure configure: clean @@ -9,7 +14,7 @@ mkdir build ; \ cd build ; \ cmake .. \ - -DCMAKE_BUILD_TYPE=RELEASE + -DCMAKE_BUILD_TYPE=RELEASE $(EXTRA_PARAMS) install: configure cd build ; \ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libyui-3.4.1/PROJECTINFO.cmake new/libyui-3.4.2/PROJECTINFO.cmake --- old/libyui-3.4.1/PROJECTINFO.cmake 2018-05-14 14:10:38.000000000 +0200 +++ new/libyui-3.4.2/PROJECTINFO.cmake 2018-07-31 09:50:54.000000000 +0200 @@ -4,7 +4,7 @@ ##### MAKE ALL NEEDED CHANGES HERE ##### -SET( SUBDIRS src examples ) +SET( SUBDIRS src examples tests ) SET( LIB_DEPS Boost ) SET( LIB_LINKER dl pthread ) SET( EXTRA_INCLUDES ) # set include-dir which are not picked by CMake automagically here. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libyui-3.4.1/README.md new/libyui-3.4.2/README.md --- old/libyui-3.4.1/README.md 2018-05-14 14:10:38.000000000 +0200 +++ new/libyui-3.4.2/README.md 2018-07-31 09:50:54.000000000 +0200 @@ -1,6 +1,9 @@ # LibYUI - The Base Library [](https://travis-ci.org/libyui/libyui) +[]( +https://coveralls.io/github/libyui/libyui?branch=master) Libyui is a widget abstraction library providing Qt, GTK and ncurses frontends. Originally it was developed for [YaST](https://yast.github.io/) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libyui-3.4.1/VERSION.cmake new/libyui-3.4.2/VERSION.cmake --- old/libyui-3.4.1/VERSION.cmake 2018-05-14 14:10:38.000000000 +0200 +++ new/libyui-3.4.2/VERSION.cmake 2018-07-31 09:50:54.000000000 +0200 @@ -1,6 +1,6 @@ SET( VERSION_MAJOR "3") SET( VERSION_MINOR "4" ) -SET( VERSION_PATCH "1" ) +SET( VERSION_PATCH "2" ) SET( VERSION "${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}${GIT_SHA1_VERSION}" ) ##### This is need for the libyui core, ONLY. @@ -8,7 +8,7 @@ # Currently you must also change so_version in libyui.spec # *and also in **all** other* libyui-*.spec files in the other repositories. # Yes, such a design is suboptimal. -SET( SONAME_MAJOR "8" ) -SET( SONAME_MINOR "1" ) +SET( SONAME_MAJOR "9" ) +SET( SONAME_MINOR "0" ) SET( SONAME_PATCH "0" ) SET( SONAME "${SONAME_MAJOR}.${SONAME_MINOR}.${SONAME_PATCH}" ) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libyui-3.4.1/buildtools/LibyuiCommon.cmake new/libyui-3.4.2/buildtools/LibyuiCommon.cmake --- old/libyui-3.4.1/buildtools/LibyuiCommon.cmake 2018-05-14 14:10:38.000000000 +0200 +++ new/libyui-3.4.2/buildtools/LibyuiCommon.cmake 2018-07-31 09:50:54.000000000 +0200 @@ -58,6 +58,8 @@ OPTION( ENABLE_WERROR "Enable the -Werror compiler-flag?" ON ) OPTION( RESPECT_FLAGS "Shall I respect the system c/ldflags?" OFF ) OPTION( INSTALL_DOCS "Shall \"make install\" install the docs?" OFF ) + OPTION( ENABLE_TESTS "Enable tests?" ON) + OPTION( ENABLE_CODE_COVERAGE "Enable code coverage report?" OFF) ENDMACRO( SET_OPTIONS ) @@ -116,6 +118,59 @@ ) ENDIF( NOT BUILD_TYPE_PASSED ) + IF ( ENABLE_TESTS OR ENABLE_CODE_COVERAGE) + ENABLE_TESTING() + # add a wrapper "tests" target, the builtin "test" cannot be extended :-( + ADD_CUSTOM_TARGET(tests + $(MAKE) + COMMAND $(MAKE) test + ) + ENDIF ( ENABLE_TESTS OR ENABLE_CODE_COVERAGE) + + IF ( ENABLE_CODE_COVERAGE ) + # pass the coverage options to GCC + ADD_DEFINITIONS(--coverage) + LINK_LIBRARIES(--coverage) + # force debug build to not optimize the code, the optimized out code + # might be reported as not covered + SET( CMAKE_BUILD_TYPE DEBUG CACHE + STRING "set to DEBUG" + FORCE + ) + + FIND_PROGRAM( LCOV_PATH lcov ) + FIND_PROGRAM( GENHTML_PATH genhtml ) + + IF(LCOV_PATH AND GENHTML_PATH) + # save the coverage data to coverage/ subdir + SET(COVERAGE_DATA "coverage/coverage.info") + ADD_CUSTOM_TARGET(coverage + # remove the previous coverage data + rm -rf coverage/* + COMMAND mkdir -p coverage + # collect the coverage data, ignore external files (/usr/include/...), ignore tests + COMMAND ${LCOV_PATH} --no-external --exclude '*/tests/*' -o ${COVERAGE_DATA} -c -d . -q + # generate the HTML coverage report + COMMAND ${GENHTML_PATH} -o coverage --legend --title "libyui code coverage" -q ${COVERAGE_DATA} + # print the coverage summary on the terminal + COMMAND ${LCOV_PATH} --list ${COVERAGE_DATA} + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} + COMMENT "Generating the code coverage report..." + ) + # display a comment when finished + ADD_CUSTOM_COMMAND(TARGET coverage POST_BUILD + COMMAND ; + COMMENT "Code coverage gerated to ./coverage/index.html file." + ) + # automatically collect code coverage after "tests" target is finished + ADD_CUSTOM_COMMAND(TARGET tests POST_BUILD + COMMAND $(MAKE) coverage + ) + ELSE(LCOV_PATH AND GENHTML_PATH) + MESSAGE(FATAL_ERROR "lcov is not installed, code coverage report cannot be generated.") + ENDIF(LCOV_PATH AND GENHTML_PATH) + ENDIF ( ENABLE_CODE_COVERAGE ) + SET( CMAKE_CXX_FLAGS_DEBUG "-O0 -g3" ) SET( CMAKE_C_FLAGS_DEBUG "-O0 -g3" ) SET( CMAKE_CXX_FLAGS_MINSIZEREL "-Os" ) @@ -566,6 +621,8 @@ ENDIF( ENABLE_DEBUG OR ${CMAKE_BUILD_TYPE} STREQUAL "RELWITHDEBINFO" OR ${CMAKE_BUILD_TYPE} STREQUAL "DEBUG" ) MESSAGE( STATUS " Build a static library, too: ${ENABLE_STATIC}" ) MESSAGE( STATUS " Build the examples, too: ${ENABLE_EXAMPLES}" ) + MESSAGE( STATUS " Build the tests, too: ${ENABLE_TESTS}" ) + MESSAGE( STATUS " Generate test code coverage: ${ENABLE_CODE_COVERAGE}" ) MESSAGE( STATUS "" ) IF( INSTALL_DOCS AND DOXYGEN_FOUND ) MESSAGE( STATUS "RUN `make docs` BEFORE `make install` !!!" ) @@ -723,3 +780,25 @@ ) ENDMACRO( PROCESS_EXAMPLES ) + + + +MACRO( PROCESS_TESTS ) + + FIND_PACKAGE(Boost COMPONENTS unit_test_framework REQUIRED) + INCLUDE_DIRECTORIES(${Boost_INCLUDE_DIRS} ../src ${CMAKE_INCLUDE_PATH} ) + ADD_DEFINITIONS(-DBOOST_TEST_DYN_LINK -DTESTS_SRC_DIR="${CMAKE_CURRENT_SOURCE_DIR}" ) + + # expect the tests in *_test.cc files + FILE(GLOB unit_tests "*_test.cc") + FOREACH(unit_test ${unit_tests}) + # strip the .cc suffix + GET_FILENAME_COMPONENT(unit_test_bin ${unit_test} NAME_WE) + # build the test executable + ADD_EXECUTABLE(${unit_test_bin} ${unit_test}) + TARGET_LINK_LIBRARIES (${unit_test_bin} ${BASELIB} ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY} ) + # add it to the test suite + ADD_TEST(NAME ${unit_test_bin} COMMAND ${unit_test_bin}) + ENDFOREACH(unit_test) + +ENDMACRO( PROCESS_TESTS ) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libyui-3.4.1/package/libyui-doc.spec new/libyui-3.4.2/package/libyui-doc.spec --- old/libyui-3.4.1/package/libyui-doc.spec 2018-05-14 14:10:38.000000000 +0200 +++ new/libyui-3.4.2/package/libyui-doc.spec 2018-07-31 09:50:54.000000000 +0200 @@ -17,10 +17,10 @@ %define parent libyui -%define so_version 8 +%define so_version 9 Name: %{parent}-doc -Version: 3.4.1 +Version: 3.4.2 Release: 0 Source: %{parent}-%{version}.tar.bz2 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libyui-3.4.1/package/libyui.changes new/libyui-3.4.2/package/libyui.changes --- old/libyui-3.4.1/package/libyui.changes 2018-05-14 14:10:38.000000000 +0200 +++ new/libyui-3.4.2/package/libyui.changes 2018-07-31 09:50:54.000000000 +0200 @@ -1,4 +1,12 @@ ------------------------------------------------------------------- +Thu Jul 26 07:45:20 UTC 2018 - [email protected] + +- Improved the FSize class to handle arbitrary sizes, use the boost + multiprecision library instead of `long long` which overflows for + values > 8EiB (bsc#991090) +- 3.4.2 + +------------------------------------------------------------------- Wed May 9 07:34:16 UTC 2018 - [email protected] - Fix GCC 8 warning: -Werror=catch-value (boo#1084636). diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libyui-3.4.1/package/libyui.spec new/libyui-3.4.2/package/libyui.spec --- old/libyui-3.4.1/package/libyui.spec 2018-05-14 14:10:38.000000000 +0200 +++ new/libyui-3.4.2/package/libyui.spec 2018-07-31 09:50:54.000000000 +0200 @@ -16,15 +16,20 @@ # Name: libyui -Version: 3.4.1 +Version: 3.4.2 Release: 0 Source: %{name}-%{version}.tar.bz2 -%define so_version 8 +%define so_version 9 %define bin_name %{name}%{so_version} +# optionally build with code coverage reporting, +# this uses debug build, do not use in production! +%bcond_with coverage + %if 0%{?suse_version} > 1325 BuildRequires: libboost_headers-devel +BuildRequires: libboost_test-devel %else BuildRequires: boost-devel %endif @@ -32,6 +37,12 @@ BuildRequires: gcc-c++ BuildRequires: pkg-config +%if %{with coverage} +# normally the coverage feature should not be used out of CI +# but to be on the safe side... +BuildRequires: lcov +%endif + Url: http://github.com/libyui/ Summary: GUI-abstraction library License: LGPL-2.1 or LGPL-3.0 @@ -69,6 +80,7 @@ %if 0%{?suse_version} > 1325 Requires: libboost_headers-devel +Requires: libboost_test-devel %else Requires: boost-devel %endif @@ -98,29 +110,41 @@ %build ./bootstrap.sh - -export CFLAGS="$RPM_OPT_FLAGS -DNDEBUG $(getconf LFS_CFLAGS)" -export CXXFLAGS="$RPM_OPT_FLAGS -DNDEBUG $(getconf LFS_CFLAGS)" - mkdir build cd build +%if %{with coverage} +CMAKE_OPTS="-DCMAKE_BUILD_TYPE=DEBUG -DENABLE_CODE_COVERAGE=ON" +# the debug build type is incompatible with the default $RPM_OPT_FLAGS, +# do not use them +export CFLAGS="-DNDEBUG $(getconf LFS_CFLAGS)" +export CXXFLAGS="-DNDEBUG $(getconf LFS_CFLAGS)" +%else +export CFLAGS="$RPM_OPT_FLAGS -DNDEBUG $(getconf LFS_CFLAGS)" +export CXXFLAGS="$RPM_OPT_FLAGS -DNDEBUG $(getconf LFS_CFLAGS)" %if %{?_with_debug:1}%{!?_with_debug:0} -cmake .. \ - -DYPREFIX=%{_prefix} \ - -DDOC_DIR=%{_docdir} \ - -DLIB_DIR=%{_lib} \ - -DCMAKE_BUILD_TYPE=RELWITHDEBINFO +CMAKE_OPTS="-DCMAKE_BUILD_TYPE=RELWITHDEBINFO" %else +CMAKE_OPTS="-DCMAKE_BUILD_TYPE=RELEASE" +%endif +%endif + cmake .. \ -DYPREFIX=%{_prefix} \ -DDOC_DIR=%{_docdir} \ -DLIB_DIR=%{_lib} \ - -DCMAKE_BUILD_TYPE=RELEASE -%endif + $CMAKE_OPTS make %{?jobs:-j%jobs} +%check +cd build +make test +%if %{with coverage} +# generate code coverage data +make coverage +%endif + %install cd build make install DESTDIR="$RPM_BUILD_ROOT" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libyui-3.4.1/src/FSize.cc new/libyui-3.4.2/src/FSize.cc --- old/libyui-3.4.1/src/FSize.cc 2018-05-14 14:10:38.000000000 +0200 +++ new/libyui-3.4.2/src/FSize.cc 2018-07-31 09:50:54.000000000 +0200 @@ -1,5 +1,7 @@ /* Copyright (C) 2000-2012 Novell, Inc + Copyright (C) 2018 SUSE LLC + This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the @@ -25,14 +27,28 @@ /-*/ -#include <stdio.h> -#include <stdlib.h> #include <iostream> +#include <sstream> #include "FSize.h" +// arbitrary precision float for floating point division +#include <boost/multiprecision/cpp_bin_float.hpp> + +using boost::multiprecision::cpp_int; + +const cpp_int FSize::KB = 1024; +const cpp_int FSize::MB = FSize::KB * 1024; +const cpp_int FSize::GB = FSize::MB * 1024; +const cpp_int FSize::TB = FSize::GB * 1024; +const cpp_int FSize::PB = FSize::TB * 1024; +const cpp_int FSize::EB = FSize::PB * 1024; +const cpp_int FSize::ZB = FSize::EB * 1024; +const cpp_int FSize::YB = FSize::ZB * 1024; + + FSize::FSize( const std::string &sizeStr, const Unit unit_r ) - : _size( atoll( sizeStr.c_str() ) * factor( unit_r ) ) + : _size( cpp_int(sizeStr) * factor( unit_r ) ) { } @@ -45,11 +61,11 @@ // FSize & FSize::fillBlock( FSize blocksize_r ) { - if ( _size && blocksize_r ) { - long long diff = _size % blocksize_r; + if ( _size > 0 && cpp_int(blocksize_r) > 0) { + cpp_int diff = _size % cpp_int(blocksize_r); if ( diff ) { if ( _size > 0 ) - _size += blocksize_r; + _size += cpp_int(blocksize_r); _size -= diff; } } @@ -65,16 +81,24 @@ // FSize::Unit FSize::bestUnit() const { - long long usize( _size < 0 ? -_size : _size ); + cpp_int usize = abs(_size); if ( usize < KB ) - return B; + return Unit::B; if ( usize < MB ) - return K; + return Unit::K; if ( usize < GB ) - return M; + return Unit::M; if ( usize < TB ) - return G; - return T; + return Unit::G; + if ( usize < PB ) + return Unit::T; + if ( usize < EB ) + return Unit::P; + if ( usize < ZB ) + return Unit::E; + if ( usize < YB ) + return Unit::Z; + return Unit::Y; } // @@ -89,26 +113,36 @@ if ( prec == bestPrec ) { switch ( unit_r ) { - case T: prec = 3; break; - case G: prec = 2; break; - case M: prec = 1; break; - case K: prec = 1; break; - case B: prec = 0; break; + case Unit::Y: prec = 3; break; + case Unit::Z: prec = 3; break; + case Unit::E: prec = 3; break; + case Unit::P: prec = 3; break; + case Unit::T: prec = 3; break; + case Unit::G: prec = 2; break; + case Unit::M: prec = 1; break; + case Unit::K: prec = 1; break; + case Unit::B: prec = 0; break; } - } else if ( unit_r == B ) +} else if ( unit_r == Unit::B ) prec = 0; // doesn't make sense for Byte - char buffer[80]; // should be long enough for any numeric sprintf() - snprintf( buffer, sizeof( buffer ), - "%*.*f", - fw, prec, ( double( _size ) / factor( unit_r ) ) ); - - std::string ret( buffer ); + std::ostringstream str; + // set the precision and field width, use fixed notation (not the scientific Xe+Y) + str << std::setprecision(prec) << std::setfill(' ') << std::setw(fw) << std::fixed; + + if (prec == 0) + // no decimal part required, we can use integer division, + // add one unit half for correct rounding + str << (_size + (factor( unit_r ) / 2))/ factor( unit_r ); + else + // otherwise convert to boost floats + str << (boost::multiprecision::cpp_bin_float_50)( _size ) / + (boost::multiprecision::cpp_bin_float_50)(factor( unit_r ) ); if ( showunit ) - ret += std::string(" ") + unit( unit_r ); + str << " " << unit( unit_r ); - return ret; + return str.str(); } @@ -123,3 +157,15 @@ { return form(); } + +std::ostream& operator<<(std::ostream &ostr, const FSize &fsize) +{ + ostr << fsize.asString(); + return ostr; +} + +std::ostream& operator<<(std::ostream &ostr, const FSize::Unit unit) +{ + ostr << FSize::unit(unit); + return ostr; +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libyui-3.4.1/src/FSize.h new/libyui-3.4.2/src/FSize.h --- old/libyui-3.4.1/src/FSize.h 2018-05-14 14:10:38.000000000 +0200 +++ new/libyui-3.4.2/src/FSize.h 2018-07-31 09:50:54.000000000 +0200 @@ -1,5 +1,6 @@ /* Copyright (C) 2000-2012 Novell, Inc + Copyright (C) 2018 SUSE LLC This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the @@ -21,7 +22,7 @@ Author: Michael Andres <[email protected]> Maintainer: Michael Andres <[email protected]> - Purpose: Store and operate on (file/package/partition) sizes (long long). + Purpose: Store and operate on (file/package/partition) sizes. /-*/ #ifndef _FSize_h_ @@ -30,45 +31,65 @@ #include <iosfwd> #include <string> +// arbitrary precision integer +#include <boost/multiprecision/cpp_int.hpp> +// generate additional operators via the boost templates +#include <boost/operators.hpp> + // // CLASS NAME : FSize // /** - * Store and operate on (file/package/partition) sizes (long long). + * Store and operate on (file/package/partition) sizes. **/ -class FSize { +class FSize : + // generate > / * + - <= => !== operators + boost::ordered_field_operators<FSize>, + // generate postfix ++ -- + boost::unit_steppable<FSize> + { public: /** * The Units **/ - enum Unit { B = 0, K, M, G, T }; + enum class Unit { B, K, M, G, T, P, E, Z, Y }; private: /** - * The size in Byte + * The size (in bytes) + * @see https://www.boost.org/doc/libs/release/libs/multiprecision/doc/html/index.html **/ - long long _size; + boost::multiprecision::cpp_int _size; public: - static const long long KB = 1024; - static const long long MB = 1024 * KB; - static const long long GB = 1024 * MB; - static const long long TB = 1024 * GB; + static const boost::multiprecision::cpp_int KB; + static const boost::multiprecision::cpp_int MB; + static const boost::multiprecision::cpp_int GB; + static const boost::multiprecision::cpp_int TB; + static const boost::multiprecision::cpp_int PB; + static const boost::multiprecision::cpp_int EB; + // these do not fit long long anymore! + static const boost::multiprecision::cpp_int ZB; + static const boost::multiprecision::cpp_int YB; /** - * Return ammount of Byte in Unit. + * Return ammount of bytes in Unit. **/ - static long long factor( const Unit unit_r ) { + static boost::multiprecision::cpp_int factor( const Unit unit_r ) { switch ( unit_r ) { - case T: return TB; - case G: return GB; - case M: return MB; - case K: return KB; - case B: break; + case Unit::Y: return YB; + case Unit::Z: return ZB; + case Unit::E: return EB; + case Unit::P: return PB; + case Unit::T: return TB; + case Unit::G: return GB; + case Unit::M: return MB; + case Unit::K: return KB; + case Unit::B: break; } return 1; } @@ -78,11 +99,15 @@ **/ static const char * unit( const Unit unit_r ) { switch ( unit_r ) { - case T: return "TB"; - case G: return "GB"; - case M: return "MB"; - case K: return "kB"; - case B: break; + case Unit::Y: return "YiB"; + case Unit::Z: return "ZiB"; + case Unit::E: return "EiB"; + case Unit::P: return "PiB"; + case Unit::T: return "TiB"; + case Unit::G: return "GiB"; + case Unit::M: return "MiB"; + case Unit::K: return "KiB"; + case Unit::B: break; } return "B"; } @@ -90,55 +115,71 @@ public: /** - * Construct from size in Byte. + * Construct from size in certain unit. + * E.g. <code>FSize( 1, FSize::Unit::K )<code> makes 1024 Byte. **/ - FSize( const long long size_r = 0 ) - : _size( size_r ) + FSize( const boost::multiprecision::cpp_int &size_r = 0, const Unit unit_r = Unit::B) + : _size( boost::multiprecision::cpp_int(size_r) * factor( unit_r ) ) {} /** - * Construct from size in certain unit. - * E.g. <code>FSize( 1, FSize::K )<code> makes 1024 Byte. + * Construct from size in Byte. + * @param size_r the initial value **/ - FSize( const long long size_r, const Unit unit_r ) - : _size( size_r * factor( unit_r ) ) + FSize( double size_r ) + : _size( size_r ) {} /** Construct from string containing a number in given unit. + * @param sizeStr input string - must contain *only* numbers + * @param unit_r optional unit, bytes by default + * @throws std::runtime_error if the string contains any non numeric characters, + * even a trailing white space! */ - FSize( const std::string &sizeStr, const Unit unit_r = B ); + FSize( const std::string &sizeStr, const Unit unit_r = Unit::B ); /** - * Conversion to long long - **/ - operator long long() const { return _size; } - - FSize & operator+=( const long long rhs ) { _size += rhs; return *this; } - FSize & operator-=( const long long rhs ) { _size -= rhs; return *this; } - FSize & operator*=( const long long rhs ) { _size *= rhs; return *this; } - FSize & operator/=( const long long rhs ) { _size /= rhs; return *this; } - - FSize & operator++(/*prefix*/) { _size += 1; return *this; } - FSize & operator--(/*prefix*/) { _size -= 1; return *this; } - - FSize operator++(int/*postfix*/) { return _size++; } - FSize operator--(int/*postfix*/) { return _size--; } + * Conversions to native data types - only explicit as it might overflow + * If the value is out of range then the behavior depends on the boost version + * - 1.67 - the min/max values for the corresponding type are returned + * - 1.66 - returns just the lower bits + **/ + explicit operator long long() const { return static_cast<long long>(_size); } + explicit operator int() const { return static_cast<int>(_size); } + explicit operator double() const { return static_cast<double>(_size); } + + operator boost::multiprecision::cpp_int() const { return _size; } + boost::multiprecision::cpp_int in_unit(const Unit unit_r) const { return _size / factor( unit_r ); } + + // unary minus + FSize operator-() const { return FSize(-_size); } + FSize & operator+=( const FSize &rhs ) { _size += boost::multiprecision::cpp_int(rhs); return *this; } + FSize & operator-=( const FSize &rhs ) { _size -= boost::multiprecision::cpp_int(rhs); return *this; } + FSize & operator*=( const FSize &rhs ) { _size *= boost::multiprecision::cpp_int(rhs); return *this; } + FSize & operator/=( const FSize &rhs ) { _size /= boost::multiprecision::cpp_int(rhs); return *this; } + + bool operator<( const FSize &rhs ) const { return _size < boost::multiprecision::cpp_int(rhs); } + bool operator==( const FSize &rhs ) const { return _size == boost::multiprecision::cpp_int(rhs); } + + // ++operator (the prefix variant) + FSize & operator++() { _size += 1; return *this; } + // --operator (the prefix variant) + FSize & operator--() { _size -= 1; return *this; } /** * Adjust size to multiple of <code>blocksize_r</code> **/ - FSize & fillBlock( FSize blocksize_r = KB ); + FSize & fillBlock( FSize blocksize_r = boost::multiprecision::cpp_int(KB) ); /** - * Return size adjusted to multiple of <code>blocksize_r</code> + * Return a new size adjusted to multiple of <code>blocksize_r</code> **/ - FSize fullBlock( FSize blocksize_r = KB ) const { FSize ret( _size ); return ret.fillBlock( blocksize_r ); } - - /** - * Return size in Unit ( not rounded ) - **/ - long long operator()( const Unit unit_r ) const { return _size / factor( unit_r ); } + FSize fullBlock( FSize blocksize_r = boost::multiprecision::cpp_int(KB) ) const + { + FSize ret( _size ); + return ret.fillBlock( blocksize_r ); + } /** * Return the best unit for string representation. @@ -176,5 +217,8 @@ std::string asString() const; }; +// stream operators +std::ostream& operator<<(std::ostream &ostr, const FSize&); +std::ostream& operator<<(std::ostream &ostr, const FSize::Unit); #endif // _FSize_h_ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libyui-3.4.1/tests/CMakeLists.txt new/libyui-3.4.2/tests/CMakeLists.txt --- old/libyui-3.4.1/tests/CMakeLists.txt 1970-01-01 01:00:00.000000000 +0100 +++ new/libyui-3.4.2/tests/CMakeLists.txt 2018-07-31 09:50:54.000000000 +0200 @@ -0,0 +1 @@ +PROCESS_TESTS() diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libyui-3.4.1/tests/FSize_test.cc new/libyui-3.4.2/tests/FSize_test.cc --- old/libyui-3.4.1/tests/FSize_test.cc 1970-01-01 01:00:00.000000000 +0100 +++ new/libyui-3.4.2/tests/FSize_test.cc 2018-07-31 09:50:54.000000000 +0200 @@ -0,0 +1,419 @@ +/* + Copyright (C) 2018 SUSE LLC + + This library is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) version 3.0 of the License. This library + 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 Lesser General Public + License for more details. You should have received a copy of the GNU + Lesser General Public License along with this library; if not, write + to the Free Software Foundation, Inc., 51 Franklin Street, Fifth + Floor, Boston, MA 02110-1301 USA +*/ + +// This is an unit test for the FSize class + +#define BOOST_TEST_MODULE FSize_tests +#include <boost/test/unit_test.hpp> +#include <boost/version.hpp> + +#include <limits> +#include <sstream> + +#include "FSize.h" + +using boost::multiprecision::cpp_int; + +// decrease the log level to warnings +struct LogWarnings { + // global initialization before running any test + void setup() { + boost::unit_test::unit_test_log.set_threshold_level( boost::unit_test::log_warnings ); + } + // cleanup after all tests are finished + void teardown() { } +}; + +BOOST_TEST_GLOBAL_FIXTURE( LogWarnings ); + +BOOST_AUTO_TEST_CASE( constructor ) +{ + // check the default constructor + FSize fsize; + BOOST_CHECK_EQUAL( fsize, 0 ); + + // check an int parameter + FSize fsize_int(42); + BOOST_CHECK_EQUAL( fsize_int, 42 ); + + // check a long long parameter + FSize fsize_long(1LL << 40); + BOOST_CHECK_EQUAL( fsize_long, 1LL << 40); + + // check a double parameter + FSize fsize_double(42.0); + BOOST_CHECK_EQUAL( fsize_double, 42.0); + // the decimal part is ignored + BOOST_CHECK_EQUAL( fsize_double, FSize(42.1)); + BOOST_CHECK_EQUAL( fsize_double, FSize(42.5)); + BOOST_CHECK_EQUAL( fsize_double, FSize(42.9)); + + // check negative number + FSize fsize_int_neg(-42); + BOOST_CHECK_EQUAL( fsize_int_neg, -42 ); + + // create with units + long long u = 1; + BOOST_CHECK_EQUAL( FSize(1, FSize::Unit::B), 1); + BOOST_CHECK_EQUAL( FSize(1, FSize::Unit::K), u *= 1024); + BOOST_CHECK_EQUAL( FSize(1, FSize::Unit::M), u *= 1024); + BOOST_CHECK_EQUAL( FSize(1, FSize::Unit::G), u *= 1024); + BOOST_CHECK_EQUAL( FSize(1, FSize::Unit::T), u *= 1024); + BOOST_CHECK_EQUAL( FSize(1, FSize::Unit::P), u *= 1024); + BOOST_CHECK_EQUAL( FSize(1, FSize::Unit::E), u *= 1024); + // too much for a long long... + BOOST_CHECK_EQUAL( FSize(1, FSize::Unit::Z), cpp_int(1) << 70); + BOOST_CHECK_EQUAL( FSize(1, FSize::Unit::Y), cpp_int(1) << 80); + + BOOST_CHECK_EQUAL( FSize(128, FSize::Unit::K), 128 * 1024); + BOOST_CHECK_EQUAL( FSize(-128, FSize::Unit::K), -(128 * 1024)); + + // from string + BOOST_CHECK_EQUAL( FSize("128", FSize::Unit::K), 128 * 1024); + BOOST_CHECK_EQUAL( FSize("-128", FSize::Unit::K), -128 * 1024); + BOOST_CHECK_EQUAL( FSize("856", FSize::Unit::M), 856 * 1024 * 1024); + + // throws std::runtime_error exception for invalid data!! + BOOST_CHECK_THROW( FSize("72.89", FSize::Unit::K), std::runtime_error); + BOOST_CHECK_THROW( FSize(" 72 ", FSize::Unit::K), std::runtime_error); + BOOST_CHECK_THROW( FSize("72asdf", FSize::Unit::K), std::runtime_error); +} + +BOOST_AUTO_TEST_CASE( comparing_positive ) +{ + FSize fsize(42); + BOOST_CHECK_EQUAL( fsize == 42, true ); + BOOST_CHECK_EQUAL( fsize != 42, false ); + + BOOST_CHECK_EQUAL( fsize > 0, true ); + BOOST_CHECK_EQUAL( fsize > 10, true ); + BOOST_CHECK_EQUAL( fsize > 42, false ); + BOOST_CHECK_EQUAL( fsize > -42, true ); + + BOOST_CHECK_EQUAL( fsize >= 0, true ); + BOOST_CHECK_EQUAL( fsize >= 10, true ); + BOOST_CHECK_EQUAL( fsize >= 42, true ); + BOOST_CHECK_EQUAL( fsize >= -42, true ); + + BOOST_CHECK_EQUAL( fsize < 0, false ); + BOOST_CHECK_EQUAL( fsize < 10, false ); + BOOST_CHECK_EQUAL( fsize < 42, false ); + BOOST_CHECK_EQUAL( fsize < -42, false ); + + BOOST_CHECK_EQUAL( fsize < 0, false ); + BOOST_CHECK_EQUAL( fsize < 10, false ); + BOOST_CHECK_EQUAL( fsize <= 42, true ); + BOOST_CHECK_EQUAL( fsize <= -42, false ); +} + +BOOST_AUTO_TEST_CASE( comparing_negative ) +{ + FSize fsize(-42); + BOOST_CHECK_EQUAL( fsize == -42, true ); + BOOST_CHECK_EQUAL( fsize != -42, false ); + + BOOST_CHECK_EQUAL( fsize > 0, false ); + BOOST_CHECK_EQUAL( fsize > 10, false ); + BOOST_CHECK_EQUAL( fsize > -42, false ); + BOOST_CHECK_EQUAL( fsize > -52, true ); + + BOOST_CHECK_EQUAL( fsize >= 0, false ); + BOOST_CHECK_EQUAL( fsize >= 10, false ); + BOOST_CHECK_EQUAL( fsize >= -42, true ); + BOOST_CHECK_EQUAL( fsize >= -52, true ); + + BOOST_CHECK_EQUAL( fsize < 0, true ); + BOOST_CHECK_EQUAL( fsize < 10, true ); + BOOST_CHECK_EQUAL( fsize < 42, true ); + BOOST_CHECK_EQUAL( fsize < -42, false ); + BOOST_CHECK_EQUAL( fsize < -52, false ); + + BOOST_CHECK_EQUAL( fsize < 0, true ); + BOOST_CHECK_EQUAL( fsize < 10, true ); + BOOST_CHECK_EQUAL( fsize <= 42, true ); + BOOST_CHECK_EQUAL( fsize <= -42, true ); + BOOST_CHECK_EQUAL( fsize <= -52, false ); +} + +BOOST_AUTO_TEST_CASE( comparing_fsizes ) +{ + FSize fsize(100); + FSize fsize_copy(fsize); + FSize fsize_double(100.0); + FSize fsize_negative(-100); + FSize fsize_different(200); + + BOOST_CHECK_EQUAL( fsize, fsize_copy ); + BOOST_CHECK_EQUAL( fsize, fsize_double ); + BOOST_CHECK_NE( fsize, fsize_different ); + BOOST_CHECK_NE( fsize, fsize_negative ); + + BOOST_CHECK_EQUAL( fsize < fsize_copy, false ); + BOOST_CHECK_EQUAL( fsize > fsize_copy, false ); + BOOST_CHECK_EQUAL( fsize <= fsize_copy, true ); + BOOST_CHECK_EQUAL( fsize >= fsize_copy, true ); + BOOST_CHECK_EQUAL( fsize < fsize_different, true ); + BOOST_CHECK_EQUAL( fsize > fsize_different, false ); + BOOST_CHECK_EQUAL( fsize <= fsize_different, true ); + BOOST_CHECK_EQUAL( fsize >= fsize_different, false ); +} + +BOOST_AUTO_TEST_CASE( comparing_with_limits ) +{ + // 2^1024 + FSize fsize(cpp_int(1) << 1024); + + // even bigger than the max long long + BOOST_CHECK(fsize > std::numeric_limits<long long>::max()); + // even bigger than the max unsigned long long + BOOST_CHECK(fsize > std::numeric_limits<unsigned long long>::max()); + // even bigger than the max double + BOOST_CHECK(fsize > std::numeric_limits<double>::max()); + + // compare with the negative limits + fsize *= -1; + // even lower than the min long long + BOOST_CHECK(fsize < std::numeric_limits<long long>::min()); + // even lower than the min unsigned long long + BOOST_CHECK(fsize < std::numeric_limits<unsigned long long>::min()); + // even lower than the min double + BOOST_CHECK(fsize < std::numeric_limits<double>::min()); +} + +BOOST_AUTO_TEST_CASE( operators_on_self ) +{ + FSize fsize(42); + + fsize += 42; + BOOST_CHECK(fsize == 84); + fsize -= 42; + BOOST_CHECK(fsize == 42); + fsize -= 42; + BOOST_CHECK(fsize == 0); + fsize -= 42; + BOOST_CHECK(fsize == -42); + fsize *= -1; + BOOST_CHECK(fsize == 42); + fsize *= 8; + BOOST_CHECK(fsize == 336); + fsize /= 6; + BOOST_CHECK(fsize == 56); + + // check some bigger values, 10TiB + FSize fsize2(10, FSize::Unit::T); + // 10TiB / 10 => 1TiB + fsize2 /= 10; + BOOST_CHECK(fsize2 == FSize::TB); +} + +BOOST_AUTO_TEST_CASE( operators ) +{ + BOOST_CHECK_EQUAL(FSize(20) + FSize(22), 42); + BOOST_CHECK_EQUAL(FSize(64) - FSize(22), 42); + BOOST_CHECK_EQUAL(FSize(64) * FSize(4), 256); + BOOST_CHECK_EQUAL(FSize(1024) / FSize(8), 128); + + BOOST_CHECK_EQUAL(20 + FSize(22), 42); + BOOST_CHECK_EQUAL(64 - FSize(22), 42); + BOOST_CHECK_EQUAL(64 * FSize(4), 256); + BOOST_CHECK_EQUAL(1024 / FSize(8), 128); + + BOOST_CHECK_EQUAL(FSize(20) + 22, 42); + BOOST_CHECK_EQUAL(FSize(64) - 22, 42); + BOOST_CHECK_EQUAL(FSize(64) * 4, 256); + BOOST_CHECK_EQUAL(FSize(1024) / 8, 128); + + // unary minus + BOOST_CHECK_EQUAL(-FSize(120), -120); + + // increment/decrement + FSize test(120); + // post increment + BOOST_CHECK_EQUAL(test++, 120); + // changed + BOOST_CHECK_EQUAL(test, 121); + // pre increment + BOOST_CHECK_EQUAL(++test, 122); + // not changed + BOOST_CHECK_EQUAL(test, 122); + + // post decrement + BOOST_CHECK_EQUAL(test--, 122); + // changed + BOOST_CHECK_EQUAL(test, 121); + // pre decrement + BOOST_CHECK_EQUAL(--test, 120); + // not changed + BOOST_CHECK_EQUAL(test, 120); +} + +BOOST_AUTO_TEST_CASE( fillBlock ) +{ + BOOST_CHECK_EQUAL(FSize(0).fillBlock(), 0); + BOOST_CHECK_EQUAL(FSize(1).fillBlock(), 1024); + BOOST_CHECK_EQUAL(FSize(4000).fillBlock(), 4096); + BOOST_CHECK_EQUAL(FSize(42 * 1024).fillBlock(), 42 * 1024); + BOOST_CHECK_EQUAL(FSize(42 * 1024).fillBlock(32 * 1024), 65536); + + // fillBlock() changes the object + int value = 42 * 1024; // 42KiB + FSize fsize(value); + BOOST_CHECK_EQUAL(fsize.fillBlock(32 * 1024), 65536); + // not equal to the original size + BOOST_CHECK_NE(fsize, value); +} + +BOOST_AUTO_TEST_CASE( fullBlock ) +{ + BOOST_CHECK_EQUAL(FSize(0).fullBlock(), 0); + BOOST_CHECK_EQUAL(FSize(1).fullBlock(), 1024); + BOOST_CHECK_EQUAL(FSize(4000).fullBlock(), 4096); + BOOST_CHECK_EQUAL(FSize(42 * 1024).fullBlock(), 42 * 1024); + BOOST_CHECK_EQUAL(FSize(42 * 1024).fullBlock(32 * 1024), 65536); + + // fullBlock() creates a new object + int value = 42 * 1024; // 42KiB + FSize fsize(value); + BOOST_CHECK_EQUAL(fsize.fullBlock(32 * 1024), 65536); + // not changed + BOOST_CHECK_EQUAL(fsize, value); +} + +BOOST_AUTO_TEST_CASE( bestUnit ) +{ + BOOST_CHECK_EQUAL(FSize(0).bestUnit(), FSize::Unit::B); + BOOST_CHECK_EQUAL(FSize(999).bestUnit(), FSize::Unit::B); + BOOST_CHECK_EQUAL(FSize(1023).bestUnit(), FSize::Unit::B); + BOOST_CHECK_EQUAL(FSize(1024).bestUnit(), FSize::Unit::K); + + BOOST_CHECK_EQUAL(FSize(1LL << 20).bestUnit(), FSize::Unit::M); + BOOST_CHECK_EQUAL(FSize(1LL << 30).bestUnit(), FSize::Unit::G); + BOOST_CHECK_EQUAL(FSize(1LL << 40).bestUnit(), FSize::Unit::T); + BOOST_CHECK_EQUAL(FSize(1LL << 50).bestUnit(), FSize::Unit::P); + BOOST_CHECK_EQUAL(FSize(1LL << 60).bestUnit(), FSize::Unit::E); + BOOST_CHECK_EQUAL(FSize(cpp_int(1) << 70).bestUnit(), FSize::Unit::Z); + BOOST_CHECK_EQUAL(FSize(cpp_int(1) << 80).bestUnit(), FSize::Unit::Y); +} + +BOOST_AUTO_TEST_CASE( unit ) +{ + BOOST_CHECK_EQUAL(FSize::unit(FSize::Unit::B), "B"); + BOOST_CHECK_EQUAL(FSize::unit(FSize::Unit::K), "KiB"); + BOOST_CHECK_EQUAL(FSize::unit(FSize::Unit::M), "MiB"); + BOOST_CHECK_EQUAL(FSize::unit(FSize::Unit::G), "GiB"); + BOOST_CHECK_EQUAL(FSize::unit(FSize::Unit::T), "TiB"); + BOOST_CHECK_EQUAL(FSize::unit(FSize::Unit::P), "PiB"); + BOOST_CHECK_EQUAL(FSize::unit(FSize::Unit::E), "EiB"); + BOOST_CHECK_EQUAL(FSize::unit(FSize::Unit::Z), "ZiB"); + BOOST_CHECK_EQUAL(FSize::unit(FSize::Unit::Y), "YiB"); +} + +BOOST_AUTO_TEST_CASE( form ) +{ + BOOST_CHECK_EQUAL(FSize(0).form(), "0 B"); + BOOST_CHECK_EQUAL(FSize(1).form(), "1 B"); + BOOST_CHECK_EQUAL(FSize(1024).form(), "1.0 KiB"); + BOOST_CHECK_EQUAL(FSize(-1024).form(), "-1.0 KiB"); + BOOST_CHECK_EQUAL(FSize(FSize::MB).form(), "1.0 MiB"); + BOOST_CHECK_EQUAL(FSize(123456789).form(), "117.7 MiB"); + // requested unit + BOOST_CHECK_EQUAL(FSize(123456789).form(FSize::Unit::K), "120563.3 KiB"); + BOOST_CHECK_EQUAL(FSize(123456789).form(FSize::Unit::M), "117.7 MiB"); + BOOST_CHECK_EQUAL(FSize(123456789).form(FSize::Unit::G), "0.11 GiB"); + // too small for the required unit + BOOST_CHECK_EQUAL(FSize(123456789).form(FSize::Unit::T), "0.000 TiB"); + BOOST_CHECK_EQUAL(FSize(123456789).form(FSize::Unit::P), "0.000 PiB"); + BOOST_CHECK_EQUAL(FSize(123456789).form(FSize::Unit::E), "0.000 EiB"); + BOOST_CHECK_EQUAL(FSize(123456789).form(FSize::Unit::Z), "0.000 ZiB"); + BOOST_CHECK_EQUAL(FSize(123456789).form(FSize::Unit::Y), "0.000 YiB"); + + // field width + BOOST_CHECK_EQUAL(FSize(123456789).form(10), " 117.7 MiB"); + // the width parameter does NOT include the units! + BOOST_CHECK_EQUAL(FSize(123456789).form(10).length(), 14); + // does not cut numbers for longer strings + BOOST_CHECK_EQUAL(FSize(123456789).form(FSize::Unit::K, 5), "120563.3 KiB"); + + // precision + BOOST_CHECK_EQUAL(FSize(123456789).form(0, 3), "117.738 MiB"); + BOOST_CHECK_EQUAL(FSize(123456789).form(0, 0), "118 MiB"); + BOOST_CHECK_EQUAL(FSize(123456789).form(FSize::Unit::K, 0, 3), "120563.271 KiB"); + BOOST_CHECK_EQUAL(FSize(123456789).form(FSize::Unit::K, 0, 0), "120563 KiB"); + // precision for bytes is ignored + BOOST_CHECK_EQUAL(FSize(1234).form(FSize::Unit::B, 0, 3), "1234 B"); + + // without units + BOOST_CHECK_EQUAL(FSize(123456789).form(0, 3, false), "117.738"); + BOOST_CHECK_EQUAL(FSize(123456789).form(0, 0, false), "118"); + BOOST_CHECK_EQUAL(FSize(123456789).form(FSize::Unit::K, 0, 3, false), "120563.271"); + BOOST_CHECK_EQUAL(FSize(123456789).form(FSize::Unit::K, 0, 0, false), "120563"); +} + +BOOST_AUTO_TEST_CASE( as_string ) +{ + // the same behavior like form(), test just few examples + BOOST_CHECK_EQUAL(FSize(0).asString(), "0 B"); + BOOST_CHECK_EQUAL(FSize(1).asString(), "1 B"); + BOOST_CHECK_EQUAL(FSize(1024).asString(), "1.0 KiB"); + BOOST_CHECK_EQUAL(FSize(-1024).asString(), "-1.0 KiB"); + BOOST_CHECK_EQUAL(FSize(123456789).asString(), "117.7 MiB"); +} + +template<class T> std::string to_stream(const T& object) +{ + std::ostringstream str; + + str << object; + return str.str(); +} + +BOOST_AUTO_TEST_CASE( output_operator ) +{ + BOOST_CHECK_EQUAL(to_stream(FSize(0)), "0 B"); + BOOST_CHECK_EQUAL(to_stream(FSize(1)), "1 B"); + BOOST_CHECK_EQUAL(to_stream(FSize(1024)), "1.0 KiB"); + BOOST_CHECK_EQUAL(to_stream(FSize(1024)), "1.0 KiB"); + BOOST_CHECK_EQUAL(to_stream(FSize(123456789)), "117.7 MiB"); + + BOOST_CHECK_EQUAL(to_stream(FSize::Unit::B), "B"); + BOOST_CHECK_EQUAL(to_stream(FSize::Unit::K), "KiB"); + BOOST_CHECK_EQUAL(to_stream(FSize::Unit::M), "MiB"); + BOOST_CHECK_EQUAL(to_stream(FSize::Unit::G), "GiB"); + BOOST_CHECK_EQUAL(to_stream(FSize::Unit::T), "TiB"); + BOOST_CHECK_EQUAL(to_stream(FSize::Unit::P), "PiB"); + BOOST_CHECK_EQUAL(to_stream(FSize::Unit::E), "EiB"); + BOOST_CHECK_EQUAL(to_stream(FSize::Unit::Z), "ZiB"); + BOOST_CHECK_EQUAL(to_stream(FSize::Unit::Y), "YiB"); +} + +BOOST_AUTO_TEST_CASE( long_long_conversion ) +{ + if (BOOST_VERSION >= 106700) + { + // Boost 1.67 returns min/max values for the values out of range + // https://www.boost.org/users/history/version_1_67_0.html + BOOST_CHECK_EQUAL((long long)(FSize::ZB), std::numeric_limits<long long>::max()); + BOOST_CHECK_EQUAL((long long)(-FSize::YB), std::numeric_limits<long long>::min()); + } + else + { + // the cpp_int convertion is buggy in older boost + // the older Boost (at least the 1.66 version) returns just the lower bits + // in that case just print a warning and continue + BOOST_WARN_EQUAL((long long)(FSize::ZB), std::numeric_limits<long long>::max()); + BOOST_WARN_EQUAL((long long)(-FSize::YB), std::numeric_limits<long long>::min()); + } +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libyui-3.4.1/tests/README.md new/libyui-3.4.2/tests/README.md --- old/libyui-3.4.1/tests/README.md 1970-01-01 01:00:00.000000000 +0100 +++ new/libyui-3.4.2/tests/README.md 2018-07-31 09:50:54.000000000 +0200 @@ -0,0 +1,36 @@ + +# Unit Tests + +This directory contains unit tests. + +The unit tests are enabled by default, if you want to disable them (not +recommended!) then use the `-DENABLE_TESTS=OFF` cmake option. + + +## Writing Tests + +- The test files should end with `_test.cc` suffix. +- Use the boost test framework, see the [documentation]( +https://www.boost.org/doc/libs/release/libs/test/doc/html/index.html). + + +## Running the Tests + +Run `make test`. If some some test fails and you need to get more details +then directly run the test binary from `build/tests` directory, it will print +the details on the console. + + +## Code Coverage + +The code coverage reporting can be enabled using the `-DENABLE_CODE_COVERAGE=ON` +cmake option or using the `make -f Makefile.cvs COVERAGE=1` initial call. +The `lcov` package needs to be installed. + +To print the code coverage run `make`, `make test` and `make coverage`. +There is an additional all-in-one target which build the sources, runs the tests +and prints the code coverage - simply run `make tests`. + +The code coverage summary will be displayed on the console. If you need more +details (e.g. which lines are covered) then open the `coverage/index.html` +file in a web browser.
