Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package libupnp for openSUSE:Factory checked in at 2023-05-02 16:18:31 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/libupnp (Old) and /work/SRC/openSUSE:Factory/.libupnp.new.1533 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "libupnp" Tue May 2 16:18:31 2023 rev:34 rq:1083840 version:1.14.17 Changes: -------- --- /work/SRC/openSUSE:Factory/libupnp/libupnp.changes 2023-03-31 21:15:11.702301675 +0200 +++ /work/SRC/openSUSE:Factory/.libupnp.new.1533/libupnp.changes 2023-05-02 16:18:33.449643690 +0200 @@ -1,0 +2,7 @@ +Mon May 1 07:55:25 UTC 2023 - Jan Engelhardt <jeng...@inai.de> + +- Update to release 1.14.17 + * No user-visible changes + * Include fuzzer and gtest in the tarball + +------------------------------------------------------------------- Old: ---- libupnp-1.14.16.tar.bz2 New: ---- libupnp-1.14.17.tar.bz2 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ libupnp.spec ++++++ --- /var/tmp/diff_new_pack.rGKLnQ/_old 2023-05-02 16:18:34.001646964 +0200 +++ /var/tmp/diff_new_pack.rGKLnQ/_new 2023-05-02 16:18:34.005646987 +0200 @@ -20,7 +20,7 @@ %define pnpver 17 %define ixmlver 11 Name: libupnp -Version: 1.14.16 +Version: 1.14.17 Release: 0 Summary: An implementation of Universal Plug and Play (UPnP) License: BSD-3-Clause ++++++ libupnp-1.14.16.tar.bz2 -> libupnp-1.14.17.tar.bz2 ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libupnp-1.14.16/ChangeLog new/libupnp-1.14.17/ChangeLog --- old/libupnp-1.14.16/ChangeLog 2023-03-30 14:55:23.000000000 +0200 +++ new/libupnp-1.14.17/ChangeLog 2023-03-30 15:00:55.000000000 +0200 @@ -9,6 +9,10 @@ Aborted. ******************************************************************************* +Version 1.14.17 +******************************************************************************* + +******************************************************************************* Version 1.14.16 ******************************************************************************* diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libupnp-1.14.16/Makefile.am new/libupnp-1.14.17/Makefile.am --- old/libupnp-1.14.16/Makefile.am 2022-11-19 02:51:58.000000000 +0100 +++ new/libupnp-1.14.17/Makefile.am 2023-05-01 00:24:51.000000000 +0200 @@ -20,6 +20,20 @@ cmake/options.cmake \ cmake/post-test.cmake \ cmake/test-functions.cmake \ + fuzzer/FuzzIxml.c \ + fuzzer/build.sh \ + fuzzer/CMakeLists.txt \ + gtest/README.md \ + gtest/CMakeLists.txt \ + gtest/tools \ + gtest/tools/compile.sh \ + gtest/tools/README \ + gtest/tools/test_tools.cpp \ + gtest/tools/tools.cpp \ + gtest/test_UpnpHttpHeaderList.cpp \ + gtest/test_template.cpp \ + gtest/test_upnpapi.cpp \ + gtest/TODO \ IXML.cmake.in \ UPNP.cmake.in \ ixml/CMakeLists.txt \ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libupnp-1.14.16/Makefile.in new/libupnp-1.14.17/Makefile.in --- old/libupnp-1.14.16/Makefile.in 2023-03-30 14:57:59.000000000 +0200 +++ new/libupnp-1.14.17/Makefile.in 2023-05-01 00:26:48.000000000 +0200 @@ -210,7 +210,7 @@ $(top_srcdir)/upnp/inc/upnpconfig.h.in \ $(top_srcdir)/upnp/sample/common/config_sample.h.in COPYING \ ChangeLog README.md THANKS build-aux/ar-lib build-aux/compile \ - build-aux/config.guess build-aux/config.sub \ + build-aux/config.guess build-aux/config.sub build-aux/depcomp \ build-aux/install-sh build-aux/ltmain.sh build-aux/missing DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) distdir = $(PACKAGE)-$(VERSION) @@ -401,6 +401,20 @@ cmake/options.cmake \ cmake/post-test.cmake \ cmake/test-functions.cmake \ + fuzzer/FuzzIxml.c \ + fuzzer/build.sh \ + fuzzer/CMakeLists.txt \ + gtest/README.md \ + gtest/CMakeLists.txt \ + gtest/tools \ + gtest/tools/compile.sh \ + gtest/tools/README \ + gtest/tools/test_tools.cpp \ + gtest/tools/tools.cpp \ + gtest/test_UpnpHttpHeaderList.cpp \ + gtest/test_template.cpp \ + gtest/test_upnpapi.cpp \ + gtest/TODO \ IXML.cmake.in \ UPNP.cmake.in \ ixml/CMakeLists.txt \ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libupnp-1.14.16/configure new/libupnp-1.14.17/configure --- old/libupnp-1.14.16/configure 2023-03-30 14:57:58.000000000 +0200 +++ new/libupnp-1.14.17/configure 2023-05-01 00:26:48.000000000 +0200 @@ -1,6 +1,6 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.71 for libupnp 1.14.16. +# Generated by GNU Autoconf 2.71 for libupnp 1.14.17. # # Report bugs to <mrobe...@users.sourceforge.net>. # @@ -621,8 +621,8 @@ # Identity of this package. PACKAGE_NAME='libupnp' PACKAGE_TARNAME='libupnp' -PACKAGE_VERSION='1.14.16' -PACKAGE_STRING='libupnp 1.14.16' +PACKAGE_VERSION='1.14.17' +PACKAGE_STRING='libupnp 1.14.17' PACKAGE_BUGREPORT='mrobe...@users.sourceforge.net' PACKAGE_URL='' @@ -1434,7 +1434,7 @@ # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF -\`configure' configures libupnp 1.14.16 to adapt to many kinds of systems. +\`configure' configures libupnp 1.14.17 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1505,7 +1505,7 @@ if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of libupnp 1.14.16:";; + short | recursive ) echo "Configuration of libupnp 1.14.17:";; esac cat <<\_ACEOF @@ -1652,7 +1652,7 @@ test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -libupnp configure 1.14.16 +libupnp configure 1.14.17 generated by GNU Autoconf 2.71 Copyright (C) 2021 Free Software Foundation, Inc. @@ -2008,7 +2008,7 @@ This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. -It was created by libupnp $as_me 1.14.16, which was +It was created by libupnp $as_me 1.14.17, which was generated by GNU Autoconf 2.71. Invocation command line was $ $0$ac_configure_args_raw @@ -2766,7 +2766,7 @@ LT_VERSION_IXML=12:2:1 -LT_VERSION_UPNP=18:7:1 +LT_VERSION_UPNP=18:8:1 @@ -3288,7 +3288,7 @@ # Define the identity of the package. PACKAGE='libupnp' - VERSION='1.14.16' + VERSION='1.14.17' printf "%s\n" "#define PACKAGE \"$PACKAGE\"" >>confdefs.h @@ -17722,7 +17722,7 @@ # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" -This file was extended by libupnp $as_me 1.14.16, which was +This file was extended by libupnp $as_me 1.14.17, which was generated by GNU Autoconf 2.71. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -17790,7 +17790,7 @@ cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config='$ac_cs_config_escaped' ac_cs_version="\\ -libupnp config.status 1.14.16 +libupnp config.status 1.14.17 configured by $0, generated by GNU Autoconf 2.71, with options \\"\$ac_cs_config\\" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libupnp-1.14.16/configure.ac new/libupnp-1.14.17/configure.ac --- old/libupnp-1.14.16/configure.ac 2022-11-19 03:28:44.000000000 +0100 +++ new/libupnp-1.14.17/configure.ac 2023-03-30 15:02:26.000000000 +0200 @@ -9,7 +9,7 @@ AC_PREREQ(2.60) -AC_INIT([libupnp], [1.14.16], [mrobe...@users.sourceforge.net]) +AC_INIT([libupnp], [1.14.17], [mrobe...@users.sourceforge.net]) dnl ############################################################################ dnl # *Independently* of the above libupnp package version, the libtool version dnl # of the 3 libraries need to be updated whenever there is a change released: @@ -219,8 +219,18 @@ dnl #AC_SUBST([LT_VERSION_UPNP], [18:7:1]) dnl # dnl ############################################################################ +dnl # Release 1.14.17 +dnl # "current:revision:age" +dnl # +dnl # - Code has changed in upnp +dnl # revision: 7 -> 8 +dnl # +dnl #AC_SUBST([LT_VERSION_IXML], [12:2:1]) +dnl #AC_SUBST([LT_VERSION_UPNP], [18:8:1]) +dnl # +dnl ############################################################################ AC_SUBST([LT_VERSION_IXML], [12:2:1]) -AC_SUBST([LT_VERSION_UPNP], [18:7:1]) +AC_SUBST([LT_VERSION_UPNP], [18:8:1]) dnl ############################################################################ dnl # Repeating the algorithm to place it closer to the modificatin place: dnl # - library code modified: revision++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libupnp-1.14.16/docs/Doxyfile new/libupnp-1.14.17/docs/Doxyfile --- old/libupnp-1.14.16/docs/Doxyfile 2022-11-19 03:29:29.000000000 +0100 +++ new/libupnp-1.14.17/docs/Doxyfile 2023-03-30 15:03:01.000000000 +0200 @@ -38,7 +38,7 @@ # could be handy for archiving the generated documentation or if some version # control system is used. -PROJECT_NUMBER = 1.14.16 +PROJECT_NUMBER = 1.14.17 # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer a diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libupnp-1.14.16/fuzzer/CMakeLists.txt new/libupnp-1.14.17/fuzzer/CMakeLists.txt --- old/libupnp-1.14.16/fuzzer/CMakeLists.txt 1970-01-01 01:00:00.000000000 +0100 +++ new/libupnp-1.14.17/fuzzer/CMakeLists.txt 2022-10-08 18:11:49.000000000 +0200 @@ -0,0 +1,2 @@ +add_executable(FuzzIxml FuzzIxml.c) +target_link_libraries(FuzzIxml ixml_static ${LIB_FUZZING_ENGINE}) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libupnp-1.14.16/fuzzer/FuzzIxml.c new/libupnp-1.14.17/fuzzer/FuzzIxml.c --- old/libupnp-1.14.16/fuzzer/FuzzIxml.c 1970-01-01 01:00:00.000000000 +0100 +++ new/libupnp-1.14.17/fuzzer/FuzzIxml.c 2022-10-08 18:11:49.000000000 +0200 @@ -0,0 +1,56 @@ +#include <stdio.h> +#include <unistd.h> +#include <stdint.h> +#include <stdlib.h> +#include <string.h> +#include "ixml.h" + +#define kMinInputLength 10 +#define kMaxInputLength 5120 + +int CheckXML(char *filename){ + + int rc; + DOMString s; + IXML_Document *doc = NULL; + + rc = ixmlLoadDocumentEx(filename, &doc); + if (rc != IXML_SUCCESS) { + return rc; + } + + s = ixmlPrintDocument(doc); + if (s == NULL || s[0] == '\0') { + ixmlDocument_free(doc); + return 1; + } + + ixmlFreeDOMString(s); + ixmlDocument_free(doc); + + return 0; +} + +extern int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + + if (Size < kMinInputLength || Size > kMaxInputLength){ + return 1; + } + + int ret; + char filename[256]; + + sprintf(filename, "/tmp/libfuzzer.%d", getpid()); + FILE *fp = fopen(filename, "wb"); + if (!fp) { + return 0; + } + + fwrite(Data, Size, 1, fp); + fclose(fp); + + ret = CheckXML(filename); + unlink(filename); + return ret; +} + diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libupnp-1.14.16/fuzzer/build.sh new/libupnp-1.14.17/fuzzer/build.sh --- old/libupnp-1.14.16/fuzzer/build.sh 1970-01-01 01:00:00.000000000 +0100 +++ new/libupnp-1.14.17/fuzzer/build.sh 2022-10-08 18:11:49.000000000 +0200 @@ -0,0 +1,39 @@ +#!/bin/bash -eu + +build(){ + export CFLAGS="$1" + export CXXFLAGS="$1" + export LIB_FUZZING_ENGINE=-fsanitize=fuzzer + + mkdir build && cd build/ + cmake -DFUZZER=ON -DLIB_FUZZING_ENGINE="$LIB_FUZZING_ENGINE" ../../. + make -j$(nproc) + + cd fuzzer/ + + mkdir FuzzIxml_corpus + mkdir FuzzIxml_seed_corpus + + cp ../../../ixml/test/testdata/empty_attribute.xml FuzzIxml_seed_corpus/ +} + +run(){ + DIR=build/fuzzer + ./$DIR/FuzzIxml $DIR/FuzzIxml_corpus/ $DIR/FuzzIxml_seed_corpus/ +} + +if [ $1 == "ASan" ] +then + build "-O1 -fno-omit-frame-pointer -gline-tables-only -DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION -fsanitize=address -fsanitize-address-use-after-scope -fsanitize=fuzzer-no-link" +elif [ "$1" == "UBSan" ] +then + build "-O1 -fno-omit-frame-pointer -gline-tables-only -DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION -fsanitize=array-bounds,bool,builtin,enum,float-divide-by-zero,function,integer-divide-by-zero,null,object-size,return,returns-nonnull-attribute,shift,signed-integer-overflow,unsigned-integer-overflow,unreachable,vla-bound,vptr -fno-sanitize-recover=array-bounds,bool,builtin,enum,float-divide-by-zero,function,integer-divide-by-zero,null,object-size,return,returns-nonnull-attribute,shift,signed-integer-overflow,unreachable,vla-bound,vptr -fsanitize=fuzzer-no-link" +elif [ "$1" == "MSan" ] +then + build "-O1 -fno-omit-frame-pointer -gline-tables-only -DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION -fsanitize=memory -fsanitize-memory-track-origins -fsanitize=fuzzer-no-link" +elif [ "$1" == "Run" ] +then + run +else + echo "use: ./$0 ASan | UBSan | MSan | Run" +fi diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libupnp-1.14.16/gtest/CMakeLists.txt new/libupnp-1.14.17/gtest/CMakeLists.txt --- old/libupnp-1.14.16/gtest/CMakeLists.txt 1970-01-01 01:00:00.000000000 +0100 +++ new/libupnp-1.14.17/gtest/CMakeLists.txt 2022-08-03 16:14:24.000000000 +0200 @@ -0,0 +1,15 @@ +include (GoogleTest) + +UPNP_addGTest (test_template test_template.cpp + ADDITIONAL_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/../upnp/src/threadutil/ +) + +#UPNP_addGTest (test_UpnpHttpHeaderList test_UpnpHttpHeaderList.cpp +# ADDITIONAL_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/../upnp/src/threadutil/ +#) + +#if (NOT WIN32) +# UPNP_addGTest (test_upnpapi test_upnpapi.cpp +# ADDITIONAL_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/../upnp/src/threadutil/ +# ) +#endif() diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libupnp-1.14.16/gtest/README.md new/libupnp-1.14.17/gtest/README.md --- old/libupnp-1.14.16/gtest/README.md 1970-01-01 01:00:00.000000000 +0100 +++ new/libupnp-1.14.17/gtest/README.md 2022-08-03 16:14:24.000000000 +0200 @@ -0,0 +1,32 @@ +## Compile and run tests + +To be able to compile a test you have to add an entry in the local +`./CMakeLists.txt`. You can copy the entry for the `test_template.cpp` and +modify the filenames to your test files. Then you can compile the tests in the +local gtest directory with: + + cmake --build . + +Then you can run the tests, for example with: + + ./test_template-static + +If the output is messed up with logging information from the library, +redirect stderr to /dev/null: + + ./test_upnpapi-static 2>/dev/null + +## Skip tests on Github Workflow Actions + +It is possible that you have tests which are failing because fixing the bug it +is showing takes some time. To be able to push bug fixes and create pull +requests you can skip tests if they run on the Github Workflow as Action. The +test checks if the environment variable `GITHUB_ACTIONS` exists and will then +skip the test. An example for this conditional check you can find in the +test_template.cpp. If you want to see what tests are skipped on Github Actions +you can execute the test for example with: + + GITHUB_ACTIONS="true" ./test_template-static + +<br /> +// Last modified: 2021-04-06 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libupnp-1.14.16/gtest/TODO new/libupnp-1.14.17/gtest/TODO --- old/libupnp-1.14.16/gtest/TODO 1970-01-01 01:00:00.000000000 +0100 +++ new/libupnp-1.14.17/gtest/TODO 2022-08-03 16:14:24.000000000 +0200 @@ -0,0 +1,33 @@ +// Author: 2021-03-26 - Ingo Höft + +General +------- +* Make tests running on new library interface with UpnpLib structure + finished 2021-03-25 +* Running tests on the shared libupnp library + finished 2021-04-02 +* Replace compile.sh scripts with scripts for cmake if useful + finished 2021-04-02 +* Make available tests more specific with Matchers and Actions + +IPv4 Gtests for the Unix platform +--------------------------------- +* First gtest for UpnpGetIfInfo + finished 2021-03-07 +* First gtest for UpnpInit2 + finished 2021-03-16 +* First gtest for StartMiniServer +* First gtest for StopMiniServer +* First gtest for UpnpEnableWebserver + +Gtests for other platforms +-------------------------- +* Make IPv4 tests running for MS Windows + +IPv6 Gtests for the Unix platform +--------------------------------- +* First gtest for UpnpGetIfInfo +* First gtest for UpnpInit2 +* First gtest for StartMiniServer +* First gtest for StopMiniServer +* First gtest for UpnpEnableWebserver diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libupnp-1.14.16/gtest/test_UpnpHttpHeaderList.cpp new/libupnp-1.14.17/gtest/test_UpnpHttpHeaderList.cpp --- old/libupnp-1.14.16/gtest/test_UpnpHttpHeaderList.cpp 1970-01-01 01:00:00.000000000 +0100 +++ new/libupnp-1.14.17/gtest/test_UpnpHttpHeaderList.cpp 2022-08-03 16:14:24.000000000 +0200 @@ -0,0 +1,157 @@ +#include "LinkedList.h" +#include "UpnpHttpHeaders.h" +#include "httpparser.h" +#include "list.h" + +#include "gtest/gtest.h" +#include <array> +#include <utility> + +class HttpHeaderList : public ::testing::Test +{ +protected: + http_message_t msg; + UpnpListHead header_list; + + HttpHeaderList() + { + UpnpListInit(&header_list); + ListInit(&msg.headers, nullptr, [](void *elem) { + auto *hdr = static_cast<http_header_t *>(elem); + + membuffer_destroy(&hdr->name_buf); + membuffer_destroy(&hdr->value); + free(hdr); + }); + } + + ~HttpHeaderList() override + { + free_http_headers_list(&header_list); + ListDestroy(&msg.headers, true); + } + + void AddHeader(const char name[], const char value[]) noexcept + { + auto *hdr = static_cast<http_header_t *>( + calloc(1, sizeof(http_header_t))); + + membuffer_assign_str(&hdr->name_buf, name); + hdr->name = memptr{hdr->name_buf.buf, hdr->name_buf.length}; + + membuffer_assign_str(&hdr->value, value); + + ListAddTail(&msg.headers, hdr); + } + + using HttpHeadersPtr = std::unique_ptr<UpnpHttpHeaders, + decltype(&UpnpHttpHeaders_delete)>; + static HttpHeadersPtr MakeUpnpHttpHeaderList() + { + return {UpnpHttpHeaders_new(), &UpnpHttpHeaders_delete}; + } +}; + +TEST_F(HttpHeaderList, Empty) +{ + httpmsg_list_headers(&msg, &header_list); + + const UpnpListIter begin = UpnpListBegin(&header_list); + ASSERT_EQ(UpnpListNext(&header_list, begin), UpnpListEnd(&header_list)); +} + +TEST_F(HttpHeaderList, OneElement) +{ + AddHeader("foo", "bar"); + + httpmsg_list_headers(&msg, &header_list); + + const UpnpListIter begin = UpnpListBegin(&header_list); + + const auto *header = reinterpret_cast<UpnpHttpHeaders *>(begin); + ASSERT_STREQ(UpnpHttpHeaders_get_name_cstr(header), "foo"); + ASSERT_STREQ(UpnpHttpHeaders_get_value_cstr(header), "bar"); + ASSERT_EQ(UpnpHttpHeaders_get_resp_cstr(header), nullptr); + + ASSERT_EQ(UpnpListNext(&header_list, begin), UpnpListEnd(&header_list)); +} + +TEST_F(HttpHeaderList, OneElementMixedCase) +{ + AddHeader("USER-AGENT", "Linux"); + + httpmsg_list_headers(&msg, &header_list); + + const UpnpListIter begin = UpnpListBegin(&header_list); + + const auto *header = reinterpret_cast<UpnpHttpHeaders *>(begin); + ASSERT_STREQ(UpnpHttpHeaders_get_name_cstr(header), "USER-AGENT"); + ASSERT_STREQ(UpnpHttpHeaders_get_value_cstr(header), "Linux"); + ASSERT_EQ(UpnpHttpHeaders_get_resp_cstr(header), nullptr); + + ASSERT_EQ(UpnpListNext(&header_list, begin), UpnpListEnd(&header_list)); +} + +TEST_F(HttpHeaderList, TwoElements) +{ + AddHeader("USER-AGENT", "Darwin"); + AddHeader("Connection", "close"); + + httpmsg_list_headers(&msg, &header_list); + + const UpnpListIter first = UpnpListBegin(&header_list); + + const auto *header = reinterpret_cast<UpnpHttpHeaders *>(first); + ASSERT_STREQ(UpnpHttpHeaders_get_name_cstr(header), "USER-AGENT"); + ASSERT_STREQ(UpnpHttpHeaders_get_value_cstr(header), "Darwin"); + ASSERT_EQ(UpnpHttpHeaders_get_resp_cstr(header), nullptr); + + const UpnpListIter second = UpnpListNext(&header_list, first); + ASSERT_NE(second, UpnpListEnd(&header_list)); + + header = reinterpret_cast<UpnpHttpHeaders *>(second); + ASSERT_STREQ(UpnpHttpHeaders_get_name_cstr(header), "Connection"); + ASSERT_STREQ(UpnpHttpHeaders_get_value_cstr(header), "close"); + ASSERT_EQ(UpnpHttpHeaders_get_resp_cstr(header), nullptr); +} + +TEST_F(HttpHeaderList, PlentyElements) +{ + /* clang-format off */ + static const std::array<std::pair<const char *, const char *>, 7> elems{{ + {"USER-AGENT", "Darwin"}, + {"Connection", "close"}, + {"content-type", "text"}, + {"pragma", "no-cache"}, + {"pragma", "no-cache"}, + {"CACHE-control", "no-CACHE"}, + {"Accept-Encoding", "gzip"} + }}; + /* clang-format on */ + + for (const auto &elem : elems) { + AddHeader(elem.first, elem.second); + } + + httpmsg_list_headers(&msg, &header_list); + + const UpnpListIter begin = UpnpListBegin(&header_list); + + auto idx = 0; + for (auto it = begin; it != UpnpListEnd(&header_list); + it = UpnpListNext(begin, it), ++idx) { + const auto *header = reinterpret_cast<UpnpHttpHeaders *>(it); + ASSERT_STREQ(UpnpHttpHeaders_get_name_cstr(header), + elems[idx].first); + ASSERT_STREQ(UpnpHttpHeaders_get_value_cstr(header), + elems[idx].second); + ASSERT_EQ(UpnpHttpHeaders_get_resp_cstr(header), nullptr); + } + ASSERT_EQ(idx, elems.size()); +} + +int main(int argc, char **argv) +{ + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libupnp-1.14.16/gtest/test_template.cpp new/libupnp-1.14.17/gtest/test_template.cpp --- old/libupnp-1.14.16/gtest/test_template.cpp 1970-01-01 01:00:00.000000000 +0100 +++ new/libupnp-1.14.17/gtest/test_template.cpp 2022-08-03 16:14:24.000000000 +0200 @@ -0,0 +1,88 @@ +// This test should always run, reporting no failure +// Author: 2021-03-06 - Ingo Höft +// Last modified: 2021-04-06 + +#include "gtest/gtest.h" + +// for TestSuites linked against the static C library +extern "C" { + //#include "upnp.h" +} + +// two macros to compare values in a range +#define EXPECT_IN_RANGE(VAL, MIN, MAX) \ + EXPECT_GE((VAL), (MIN)); \ + EXPECT_LE((VAL), (MAX)) + +#define ASSERT_IN_RANGE(VAL, MIN, MAX) \ + ASSERT_GE((VAL), (MIN)); \ + ASSERT_LE((VAL), (MAX)) + + +// simple testsuite without fixtures +//---------------------------------- +TEST(EmptyTestSuite, empty_gtest) +{ + //GTEST_SKIP(); + //GTEST_SKIP_("to show this feature"); + + // SKIP on Github Actions +#ifdef _WIN32 + char* github_action; + size_t len; + _dupenv_s(&github_action, &len, "GITHUB_ACTIONS"); +#else + char *github_action = std::getenv("GITHUB_ACTIONS"); +#endif + if(github_action) { GTEST_SKIP() + << " to show this feature"; + } +} + + +// testsuite with fixtures +//------------------------ +class EmptyFixtureTestSuite : public ::testing::Test +{ + protected: + // You can remove any or all of the following functions if their bodies would + // be empty. + + EmptyFixtureTestSuite() + { + // You can do set-up work for each test here. + } + + ~EmptyFixtureTestSuite() override + { + // You can do clean-up work that doesn't throw exceptions here. + } + + // If the constructor and destructor are not enough for setting up + // and cleaning up each test, you can define the following methods: + + void SetUp() override + { + // Code here will be called immediately after the constructor (right + // before each test). Have attention to the uppercase 'U' of SetUp(). + } + + void TearDown() override + { + // Code here will be called immediately after each test (right + // before the destructor). + } + + // Class members declared here can be used by all tests in the test suite + // for Foo. +}; + +TEST_F(EmptyFixtureTestSuite, empty_gtest_with_fixture) +{ +} + + +int main(int argc, char **argv) { + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libupnp-1.14.16/gtest/test_upnpapi.cpp new/libupnp-1.14.17/gtest/test_upnpapi.cpp --- old/libupnp-1.14.16/gtest/test_upnpapi.cpp 1970-01-01 01:00:00.000000000 +0100 +++ new/libupnp-1.14.17/gtest/test_upnpapi.cpp 2022-08-03 16:14:24.000000000 +0200 @@ -0,0 +1,326 @@ +// Mock network interfaces +// For further information look at https://stackoverflow.com/a/66498073/5014688 +// Author: 2021-03-06 - Ingo Höft +// Last modified: 2021-04-06 + +#include "gtest/gtest.h" +#include "gmock/gmock.h" +#include "upnpapi.h" +#include "upnptools.h" +#include "tools/tools.cpp" +#include "UpnpLib.h" + +using ::testing::_; +using ::testing::Return; +using ::testing::DoAll; +using ::testing::SetArgPointee; +using ::testing::AtLeast; + + +// --- mock getifaddrs ------------------------------------- +class MockGetifaddrs { +public: + MOCK_METHOD(int, getifaddrs, (struct ifaddrs**)); +}; + +MockGetifaddrs* ptrMockGetifaddrsObj = nullptr; +int getifaddrs(struct ifaddrs** ifap) { + return ptrMockGetifaddrsObj->getifaddrs(ifap); +} + +// --- mock freeifaddrs ------------------------------------ +class MockFreeifaddrs { +public: + MOCK_METHOD(void, freeifaddrs, (struct ifaddrs*)); +}; + +MockFreeifaddrs* ptrMockFreeifaddrObj = nullptr; +void freeifaddrs(struct ifaddrs* ifap) { + return ptrMockFreeifaddrObj->freeifaddrs(ifap); +} + +// --- mock bind ------------------------------------------- +class MockBind { +public: + MOCK_METHOD(int, bind, (int, const struct sockaddr*, socklen_t)); +}; + +MockBind* ptrMockBindObj = nullptr; +int bind(int sockfd, const struct sockaddr* addr, socklen_t addrlen) { + return ptrMockBindObj->bind(sockfd, addr, addrlen); +} + +// --- mock if_nametoindex --------------------------------- +class MockIf_nametoindex { +public: + MOCK_METHOD(unsigned int, if_nametoindex, (const char*)); +}; + +MockIf_nametoindex* ptrMockIf_nametoindexObj = nullptr; +unsigned int if_nametoindex(const char* ifname) { + return ptrMockIf_nametoindexObj->if_nametoindex(ifname); +} + +// --- mock listen ----------------------------------------- +class MockListen { +public: + MOCK_METHOD(int, listen, (int, int)); +}; + +MockListen* ptrMockListenObj = nullptr; +int listen(int sockfd, int backlog) { + return ptrMockListenObj->listen(sockfd, backlog); +} + +// --- mock select ----------------------------------------- +class MockSelect { +public: + MOCK_METHOD(int, select, (int nfds, fd_set* readfds, fd_set* writefds, + fd_set *exceptfds, struct timeval* timeout)); +}; + +MockSelect* ptrMockSelectObj = nullptr; +int select(int nfds, fd_set* readfds, fd_set* writefds, + fd_set* exceptfds, struct timeval* timeout) { + return ptrMockSelectObj->select(nfds, readfds, writefds, + exceptfds, timeout); +} + +// --- mock accept ----------------------------------------- +class MockAccept { +public: + MOCK_METHOD(int, accept, (int sockfd, struct sockaddr* addr, + socklen_t* addrlen)); +}; + +MockAccept* ptrMockAcceptObj = nullptr; +int accept(int sockfd, struct sockaddr* addr, socklen_t* addrlen) { + return ptrMockAcceptObj->accept(sockfd, addr, addrlen); +} + +// --- mock getsockname ------------------------------------ +// If needed + + +// --- mock setsockopt-------------------------------------- +class MockSetsockopt { +public: + MOCK_METHOD(int, setsockopt, (int sockfd, int level, int optname, + const void* optval, socklen_t optlen)); +}; + +MockSetsockopt* ptrMockSetsockoptObj = nullptr; +int setsockopt(int sockfd, int level, int optname, const void* optval, + socklen_t optlen) { + return ptrMockSetsockoptObj->setsockopt(sockfd, level, optname, + optval, optlen); +} + + +// UpnpApi Testsuite for IP4 +//========================== +class UpnpApiIPv4TestSuite: public ::testing::Test +// Fixtures for this Testsuite +{ +protected: + unsigned short PORT = 51515; + + // Instantiate the mock objects. + // The global pointer to them are set in the constructor below. + MockGetifaddrs mockGetifaddrsObj; + MockFreeifaddrs mockFreeifaddrsObj; + MockBind mockBindObj; + MockIf_nametoindex mockIf_nametoindexObj; + MockListen mockListenObj; + MockSelect mockSelectObj; + MockAccept mockAcceptObj; + MockSetsockopt mockSetsockoptObj; + + UpnpApiIPv4TestSuite() + { + // set the global pointer to the mock objects + ptrMockGetifaddrsObj = &mockGetifaddrsObj; + ptrMockFreeifaddrObj = &mockFreeifaddrsObj; + ptrMockBindObj = &mockBindObj; + ptrMockIf_nametoindexObj = &mockIf_nametoindexObj; + ptrMockListenObj = &mockListenObj; + ptrMockSelectObj = &mockSelectObj; + ptrMockAcceptObj = &mockAcceptObj; + ptrMockSetsockoptObj = &mockSetsockoptObj; + } +}; + + +TEST_F(UpnpApiIPv4TestSuite, UpnpGetIfInfo_called_with_valid_interface) +{ + // SKIP on Github Actions + char* github_action = std::getenv("GITHUB_ACTIONS"); + if(github_action) { GTEST_SKIP() + << " due to issues with googlemock"; + } + + // provide a network interface + struct ifaddrs* ifaddr = nullptr; + CIfaddr4 ifaddr4Obj; + ifaddr4Obj.set("if0v4", "192.168.99.3/11"); + ifaddr = ifaddr4Obj.get(); + + EXPECT_CALL(mockGetifaddrsObj, getifaddrs(_)) + .WillOnce(DoAll(SetArgPointee<0>(ifaddr), Return(0))); + EXPECT_CALL(mockFreeifaddrsObj, freeifaddrs(ifaddr)) + .Times(1); + EXPECT_CALL(mockIf_nametoindexObj, if_nametoindex(_)) + .WillOnce(Return(2)); + + UpnpLib* p = UpnpLib_new(); + + EXPECT_STREQ(UpnpGetErrorMessage( + UpnpGetIfInfo(p, "if0v4")), + "UPNP_E_SUCCESS"); + + // gIF_NAME mocked with getifaddrs above + EXPECT_EQ(*UpnpLib_get_gIF_NAME(p), *&"if0v4"); + // gIF_IPV4 mocked with getifaddrs above + EXPECT_EQ(*UpnpLib_get_gIF_IPV4(p), *&"192.168.99.3"); + //EXPECT_THAT(gIF_IPV4, MatchesRegex("[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}")); + EXPECT_EQ(*UpnpLib_get_gIF_IPV4_NETMASK(p), *&"255.224.0.0"); + EXPECT_EQ(*UpnpLib_get_gIF_IPV6(p), *&""); + EXPECT_EQ(UpnpLib_get_gIF_IPV6_PREFIX_LENGTH(p), (unsigned)0); + EXPECT_EQ(*UpnpLib_get_gIF_IPV6_ULA_GUA(p), *&""); + EXPECT_EQ(UpnpLib_get_gIF_IPV6_ULA_GUA_PREFIX_LENGTH(p), (unsigned)0); + // index mocked with if_nametoindex above + EXPECT_EQ(UpnpLib_get_gIF_INDEX(p), (unsigned)2); + EXPECT_EQ(UpnpLib_get_LOCAL_PORT_V4(p), (unsigned short)0); + EXPECT_EQ(UpnpLib_get_LOCAL_PORT_V6(p), (unsigned short)0); + EXPECT_EQ(UpnpLib_get_LOCAL_PORT_V6_ULA_GUA(p), (unsigned short)0); + + UpnpLib_delete(p); +} + + +TEST_F(UpnpApiIPv4TestSuite, UpnpGetIfInfo_called_with_unknown_interface) +{ + // SKIP on Github Actions + char* github_action = std::getenv("GITHUB_ACTIONS"); + if(github_action) { GTEST_SKIP() + << " due to issues with googlemock"; + } + +// GTEST_SKIP() << "due to failed github sanity check because of issue #247.\n" +// << "Comment GTEST_SKIP() in the TestSuite to enable this test."; + + // provide a network interface + struct ifaddrs* ifaddr = nullptr; + CIfaddr4 ifaddr4Obj; + ifaddr4Obj.set("eth0", "192.168.77.48/22"); + ifaddr = ifaddr4Obj.get(); + + EXPECT_CALL(mockGetifaddrsObj, getifaddrs(_)) + .WillOnce(DoAll(SetArgPointee<0>(ifaddr), Return(0))); + EXPECT_CALL(mockFreeifaddrsObj, freeifaddrs(ifaddr)) + .Times(1); + EXPECT_CALL(mockIf_nametoindexObj, if_nametoindex(_)) + .Times(0); + + UpnpLib* p = UpnpLib_new(); + + EXPECT_STREQ(UpnpGetErrorMessage( + UpnpGetIfInfo(p, "ethO")), + "UPNP_E_INVALID_INTERFACE"); + + // gIF_NAME mocked with getifaddrs above + EXPECT_EQ(*UpnpLib_get_gIF_NAME(p), *&"") + << "ATTENTION! There is a wrong upper case 'O', not zero in \"ethO\""; + // gIF_IPV4 mocked with getifaddrs above + EXPECT_EQ(*UpnpLib_get_gIF_IPV4(p), *&""); + //EXPECT_THAT(gIF_IPV4, MatchesRegex("[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}")); + EXPECT_EQ(*UpnpLib_get_gIF_IPV4_NETMASK(p), *&""); + EXPECT_EQ(*UpnpLib_get_gIF_IPV6(p), *&""); + EXPECT_EQ(UpnpLib_get_gIF_IPV6_PREFIX_LENGTH(p), (unsigned)0); + EXPECT_EQ(*UpnpLib_get_gIF_IPV6_ULA_GUA(p), *&""); + EXPECT_EQ(UpnpLib_get_gIF_IPV6_ULA_GUA_PREFIX_LENGTH(p), (unsigned)0); + // index mocked with if_nametoindex above + EXPECT_EQ(UpnpLib_get_gIF_INDEX(p), (unsigned)4294967295) + << " Which is: (unsigned)-1"; + EXPECT_EQ(UpnpLib_get_LOCAL_PORT_V4(p), (unsigned short)0); + EXPECT_EQ(UpnpLib_get_LOCAL_PORT_V6(p), (unsigned short)0); + EXPECT_EQ(UpnpLib_get_LOCAL_PORT_V6_ULA_GUA(p), (unsigned short)0); + + UpnpLib_delete(p); +} + + +TEST_F(UpnpApiIPv4TestSuite, initialize_default_UpnpInit2) +{ + // SKIP on Github Actions + char* github_action = std::getenv("GITHUB_ACTIONS"); + if(github_action) { GTEST_SKIP() + << " due to failed github sanity check because of issue #272"; + } + + // provide a network interface + struct ifaddrs* ifaddr = nullptr; + CIfaddr4 ifaddr4Obj; + ifaddr4Obj.set("if0v4", "192.168.99.3/20"); + ifaddr = ifaddr4Obj.get(); + + // expect calls to system functions (which are mocked) + EXPECT_CALL(mockGetifaddrsObj, getifaddrs(_)) + .WillOnce(DoAll(SetArgPointee<0>(ifaddr), Return(0))); + EXPECT_CALL(mockFreeifaddrsObj, freeifaddrs(ifaddr)) + .Times(1); EXPECT_CALL(mockBindObj, bind(_,_,_)) + .Times(5); + EXPECT_CALL(mockIf_nametoindexObj, if_nametoindex(_)) + .Times(1); + EXPECT_CALL(mockListenObj, listen(_,_)) + .Times(3); + EXPECT_CALL(mockSelectObj, select(_,_,_,_,_)) +// .Times(7); + .Times(AtLeast(1)); + EXPECT_CALL(mockAcceptObj, accept(_,_,_)) + .Times(3); + EXPECT_CALL(mockSetsockoptObj, setsockopt(_,_,_,_,_)) + .Times(11); + + UpnpLib* libStruct = nullptr; + + // Initialize capturing of the stderr output + CCaptureFd captFdObj; + captFdObj.capture(2); // 1 = stdout, 2 = stderr + + EXPECT_STREQ(UpnpGetErrorMessage( + UpnpInit2(&libStruct, NULL, 0, NULL)), + "UPNP_E_SUCCESS"); + + EXPECT_FALSE(captFdObj.print(std::cerr)) + << "Output to stderr is true. There should not be any output to stderr"; + + UpnpLib_delete(libStruct); +} + + +// UpnpApi common Testsuite +//------------------------- +TEST(UpnpApiTestSuite, get_handle_info) +{ + UpnpLib* p = UpnpLib_new(); + + Handle_Info **HndInfo = 0; + EXPECT_EQ(GetHandleInfo(p, 0, HndInfo), HND_INVALID); + EXPECT_EQ(GetHandleInfo(p, 1, HndInfo), HND_INVALID); + + UpnpLib_delete(p); +} + +TEST(UpnpApiTestSuite, get_error_message) +{ + EXPECT_STREQ(UpnpGetErrorMessage(0), "UPNP_E_SUCCESS"); + EXPECT_STREQ(UpnpGetErrorMessage(-121), "UPNP_E_INVALID_INTERFACE"); + EXPECT_STREQ(UpnpGetErrorMessage(1), "Unknown error code"); +} + + +int main(int argc, char **argv) { + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libupnp-1.14.16/gtest/tools/README new/libupnp-1.14.17/gtest/tools/README --- old/libupnp-1.14.16/gtest/tools/README 1970-01-01 01:00:00.000000000 +0100 +++ new/libupnp-1.14.17/gtest/tools/README 2022-08-03 16:14:24.000000000 +0200 @@ -0,0 +1,4 @@ +// Author: 2021-03-17 - Ingo Höft + +Additional helper programs to initialize and improve tests. +You can compile it with ./compile.sh test_tools.cpp. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libupnp-1.14.16/gtest/tools/compile.sh new/libupnp-1.14.17/gtest/tools/compile.sh --- old/libupnp-1.14.16/gtest/tools/compile.sh 1970-01-01 01:00:00.000000000 +0100 +++ new/libupnp-1.14.17/gtest/tools/compile.sh 2022-08-03 16:14:24.000000000 +0200 @@ -0,0 +1,27 @@ +#!/usr/bin/bash + +if [ "$#" -ne 1 ]; then + >&2 echo "Compile with: $0 test_tools.cpp" + >&2 echo 'Set BUILD_DIR to point to the pupnp build directory' +fi + +BUILD_DIR="../.." + +TESTNAME=$(/usr/bin/basename -s.cpp "$1") +/usr/bin/g++ -std=c++11 -pedantic-errors -Wall \ +-o"$TESTNAME".a \ +-I"$BUILD_DIR"/_deps/googletest-src/googletest/include \ +-I"$BUILD_DIR"/_deps/googletest-src/googlemock/include \ +-I"$BUILD_DIR" \ +-I"$BUILD_DIR"/upnp/src \ +-I"$BUILD_DIR"/upnp/inc \ +-I"$BUILD_DIR"/upnp/src/inc \ +-I"$BUILD_DIR"/upnp/src/threadutil \ +-I"$BUILD_DIR"/ixml/inc \ +-DUPNP_ENABLE_IPV6 \ +"$1" \ +"$BUILD_DIR"/lib/libgtestd.a \ +"$BUILD_DIR"/lib/libgmockd.a \ +"$BUILD_DIR"/upnp/libupnp.a \ +"$BUILD_DIR"/ixml/libixml.a \ +-lpthread diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libupnp-1.14.16/gtest/tools/test_tools.cpp new/libupnp-1.14.17/gtest/tools/test_tools.cpp --- old/libupnp-1.14.16/gtest/tools/test_tools.cpp 1970-01-01 01:00:00.000000000 +0100 +++ new/libupnp-1.14.17/gtest/tools/test_tools.cpp 2022-08-03 16:14:24.000000000 +0200 @@ -0,0 +1,77 @@ +// Testing the tools, of course ;-) +// Author: 2021-03-12 - Ingo Höft + +#include "gtest/gtest.h" +#include "tools.cpp" + +TEST(ToolsTestSuite, initializing_interface_addresses) +{ + struct ifaddrs* ifaddr = nullptr; + struct sockaddr_in* ifa_addr_in = nullptr; + struct sockaddr_in* ifa_netmask_in = nullptr; + struct sockaddr_in* ifa_ifu_in = nullptr; + + CIfaddr4 ifaddr4Obj; + ifaddr = ifaddr4Obj.get(); + + EXPECT_EQ(ifaddr->ifa_next, nullptr); + EXPECT_STREQ(ifaddr->ifa_name, "lo"); + EXPECT_EQ(ifaddr->ifa_flags, (const unsigned int)0 | IFF_LOOPBACK | IFF_UP); + ifa_addr_in = (sockaddr_in*)ifaddr->ifa_addr; + EXPECT_EQ(ifa_addr_in->sin_family, AF_INET); + EXPECT_EQ(ifa_addr_in->sin_addr.s_addr, (const unsigned int)16777343); + ifa_netmask_in = (sockaddr_in*)ifaddr->ifa_netmask; + EXPECT_EQ(ifa_netmask_in->sin_family, AF_INET); + EXPECT_EQ(ifa_netmask_in->sin_addr.s_addr, (const unsigned int)255); + ifa_ifu_in = (sockaddr_in*)ifaddr->ifa_broadaddr; + EXPECT_EQ(ifa_ifu_in->sin_family, AF_INET); + EXPECT_EQ(ifa_ifu_in->sin_addr.s_addr, (const unsigned int)0); + EXPECT_EQ(ifaddr->ifa_data, nullptr); + + EXPECT_TRUE(ifaddr4Obj.set("if0v4", "192.168.168.168/20")); + EXPECT_STREQ(ifaddr->ifa_name, "if0v4"); + EXPECT_EQ(ifa_addr_in->sin_addr.s_addr, (const unsigned int)2829625536); + EXPECT_EQ(ifa_netmask_in->sin_addr.s_addr, (const unsigned int)15794175); + EXPECT_EQ(ifaddr->ifa_flags, (const unsigned int)0 | IFF_UP | IFF_BROADCAST | IFF_MULTICAST); + char broadcast_address[INET_ADDRSTRLEN]; + inet_ntop(AF_INET, &ifa_ifu_in->sin_addr.s_addr, broadcast_address, INET_ADDRSTRLEN); + EXPECT_STREQ(broadcast_address, "192.168.175.255"); + + EXPECT_TRUE(ifaddr4Obj.set("if1v4", "10.168.168.200")); + EXPECT_EQ(ifa_addr_in->sin_addr.s_addr, (const unsigned int)3366496266); + EXPECT_EQ(ifa_netmask_in->sin_addr.s_addr, (const unsigned int)4294967295); + EXPECT_EQ(ifaddr->ifa_flags, (const unsigned int)0 | IFF_UP | IFF_BROADCAST | IFF_MULTICAST); + inet_ntop(AF_INET, &ifa_ifu_in->sin_addr.s_addr, broadcast_address, INET_ADDRSTRLEN); + EXPECT_STREQ(broadcast_address, "10.168.168.200"); + + //EXPECT_TRUE(ifaddr4Obj.set("if0v4", "10.168.168.200/")); + //EXPECT_ANY_THROW(std::__cxx11::stoi("")); +} + + +TEST(ToolsTestSuite, capture_output) +{ + CCaptureFd captFdObj; + captFdObj.capture(2); // 1 = stdout, 2 = stderr + std::cerr << "1: output 1 to stderr captured\n"; + std::cerr << "2: output 1 to stderr captured\n"; + EXPECT_TRUE(captFdObj.print(std::cerr)); + std::cerr << "output 1 to stderr\n"; + + captFdObj.capture(2); + EXPECT_FALSE(captFdObj.print(std::cerr)); + captFdObj.capture(2); + std::cerr << "1: output 2 to stderr captured\n"; + EXPECT_TRUE(captFdObj.print(std::cout)); + std::cerr << "output 2 to stderr\n"; + captFdObj.capture(2); + // nothing captured + EXPECT_FALSE(captFdObj.print(std::cerr)); + std::cerr << "output 3 to stderr\n"; +} + + +int main(int argc, char **argv) { + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libupnp-1.14.16/gtest/tools/tools.cpp new/libupnp-1.14.17/gtest/tools/tools.cpp --- old/libupnp-1.14.16/gtest/tools/tools.cpp 1970-01-01 01:00:00.000000000 +0100 +++ new/libupnp-1.14.17/gtest/tools/tools.cpp 2022-08-03 16:14:24.000000000 +0200 @@ -0,0 +1,178 @@ +// Tools and helper classes to manage gtests +// Author: 2021-03-12 - Ingo Höft + +#include <ifaddrs.h> +#include <arpa/inet.h> +#include <net/if.h> +#include <iostream> +#include <fstream> +#include <fcntl.h> + + +class CIfaddr4 +// Tool to manage and fill a socket address structure. This is needed +// for mocked network interfaces. +{ + struct sockaddr_in ifa_addr; // network address + struct sockaddr_in ifa_netmask; // netmask + struct sockaddr_in ifa_ifu; // broadcast addr or point-to-point dest addr + struct ifaddrs ifaddr; + + // the bitmask is the offset in the netmasks array. + std::string netmasks[33] = {"0.0.0.0", + "128.0.0.0", "192.0.0.0", "224.0.0.0", "240.0.0.0", + "248.0.0.0", "252.0.0.0", "254.0.0.0", "255.0.0.0", + "255.128.0.0", "255.192.0.0", "255.224.0.0", "255.240.0.0", + "255.248.0.0", "255.252.0.0", "255.254.0.0", "255.255.0.0", + "255.255.128.0", "255.255.192.0", "255.255.224.0", "255.255.240.0", + "255.255.248.0", "255.255.252.0", "255.255.254.0", "255.255.255.0", + "255.255.255.128", "255.255.255.192", "255.255.255.224", "255.255.255.240", + "255.255.255.248", "255.255.255.252", "255.255.255.254", "255.255.255.255"}; +public: + CIfaddr4() + // With constructing the object you get a loopback device by default. + { + // loopback interface + //------------------- + // set network address + ifa_addr.sin_family = AF_INET; + //ifa_addr.sin_port = htons(MYPORT); + inet_aton("127.0.0.1", &(ifa_addr.sin_addr)); + + // set netmask + ifa_netmask.sin_family = AF_INET; + //ifa_netmask.sin_port = htons(MYPORT); + inet_aton("255.0.0.0", &(ifa_netmask.sin_addr)); + + // set broadcast address or Point-to-point destination address + ifa_ifu.sin_family = AF_INET; + //ifa_ifu.sin_port = htons(MYPORT); + inet_aton("0.0.0.0", &(ifa_ifu.sin_addr)); + + ifaddr.ifa_next = nullptr; // pointer to next ifaddrs structure + ifaddr.ifa_name = (char*)"lo"; + // v-- Flags from SIOCGIFFLAGS, man 7 netdevice + ifaddr.ifa_flags = 0 | IFF_LOOPBACK | IFF_UP; + ifaddr.ifa_addr = (struct sockaddr*)&ifa_addr; + ifaddr.ifa_netmask = (struct sockaddr*)&ifa_netmask; + ifaddr.ifa_broadaddr = (struct sockaddr*)&ifa_ifu; + ifaddr.ifa_data = nullptr; + } + + + ifaddrs* get() + // Return the pointer to the ifaddr structure + { + return &ifaddr; + } + + + bool set(std::string pIfname, std::string pIfaddress) + // Set the interface name and the ipv4 address with bitmask. Properties are + // set to an ipv4 UP interface, supporting broadcast and multicast. + // Returns true if successful. + { + ifaddr.ifa_name = (char*)pIfname.c_str(); + + // get the netmask from the bitmask + // the bitmask is the offset in the netmasks array. + std::size_t slashpos = pIfaddress.find_first_of("/"); + std::string address = pIfaddress; + std::string bitmask = "32"; + if (slashpos != std::string::npos) { + address = pIfaddress.substr(0,slashpos); + bitmask = pIfaddress.substr(slashpos+1); + } + //std::cout << "address: '" << address << "', bitmask: '" << bitmask << "', netmask: " + // << netmasks[std::stoi(bitmask)] << ", slashpos: " << slashpos << "\n"; + + // convert address strings to numbers and store them + inet_aton(address.c_str(), &(ifa_addr.sin_addr)); + std::string netmask = netmasks[std::stoi(bitmask)]; + inet_aton(netmask.c_str(), &(ifa_netmask.sin_addr)); + ifaddr.ifa_flags = 0 | IFF_UP | IFF_BROADCAST | IFF_MULTICAST; + + // calculate broadcast address as follows: broadcast = ip | ( ~ subnet ) + // broadcast = ip-addr or the inverted subnet-mask + ifa_ifu.sin_addr.s_addr = ifa_addr.sin_addr.s_addr | ~ ifa_netmask.sin_addr.s_addr; + + return true; + } +}; + +class CCaptureFd +// Tool to capture output to a file descriptor, mainly used to capture program +// output to stdout or stderr. +// When printing the captured output, all opened file descriptor will be closed +// to avoid confusing output loops. For a new capture after print(..) you have +// to call capture(..) again. +{ + int mFd; + int mFd_old; + int mFd_log; + bool mErr = true; + char mCaptFname[16] = ".captfd.log"; + +public: + void capture(int fd) + { + mFd = fd; + mFd_old = dup(fd); + if (mFd_old < 0) { + return; + } + mFd_log = ::open(mCaptFname, O_WRONLY|O_CREAT|O_TRUNC, 0660); + if (mFd_log < 0) { + ::close(mFd_old); + return; + } + if (dup2(mFd_log, fd) < 0) { + ::close(mFd_old); + ::close(mFd_log); + return; + } + mErr = false; + } + + ~CCaptureFd() + { + this->closeFds(); + remove(mCaptFname); + } + + bool print(std::ostream &pOut) + // Close all file descriptors and print captured file content. + // If nothing was captured, then the return value is false. + { + if (mErr) return false; + this->closeFds(); + + std::ifstream readFileObj(mCaptFname); + std::string lineBuf = ""; + + std::getline(readFileObj, lineBuf); + if (lineBuf == "") { + readFileObj.close(); + remove(mCaptFname); + return false; + } + + pOut << lineBuf << "\n"; + while (std::getline(readFileObj, lineBuf)) + pOut << lineBuf << "\n"; + + readFileObj.close(); + remove(mCaptFname); + return true; + } + +private: + void closeFds() + { + // restore old fd + dup2(mFd_old, mFd); + ::close(mFd_old); + ::close(mFd_log); + mErr = true; + } +}; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libupnp-1.14.16/libupnp.spec new/libupnp-1.14.17/libupnp.spec --- old/libupnp-1.14.16/libupnp.spec 2022-11-19 03:29:49.000000000 +0100 +++ new/libupnp-1.14.17/libupnp.spec 2023-03-30 15:00:35.000000000 +0200 @@ -1,4 +1,4 @@ -Version: 1.14.16 +Version: 1.14.17 Summary: Universal Plug and Play (UPnP) SDK Name: libupnp-1.14 Release: 1%{?dist}