From patchwork Fri Dec 12 12:03:46 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gert Doering X-Patchwork-Id: 4679 Return-Path: Delivered-To: patchwork@openvpn.net Received: by 2002:a05:7001:1490:b0:7b1:439f:bdf with SMTP id bf16csp87778mac; Fri, 12 Dec 2025 04:04:16 -0800 (PST) X-Forwarded-Encrypted: i=2; AJvYcCV9xh34RTgfqxbRNFHLiMjDg7TSfabBpm6wmPwnti7Nf17vrrDbAVF3lzLiyWKy92wQUithzgQSbaQ=@openvpn.net X-Google-Smtp-Source: AGHT+IHyBCTp55LCxCfqOa0mBryYB/33u/M+WPOJdRBdFE1bwP7tDCPrOHWPAn1Lmg7/GxG94BAA X-Received: by 2002:a05:6870:d8ce:b0:3ec:7947:33ac with SMTP id 586e51a60fabf-3f5f975c1cemr975836fac.16.1765541055907; Fri, 12 Dec 2025 04:04:15 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1765541055; cv=none; d=google.com; s=arc-20240605; b=U6oZN+SbJuH6I7wIcEWf4Ypma5U6R+TjgjOmhVP+3wb4e3wxrjhBNldjW+aFdkD/C7 2EWNcgeL+xIbUsIsYUgKtFlaNwjhOaN2OzY+R6ojLGjkhMTH4l44v8Q4QVqqlv8z/QF+ MOpISOOpNMedTEg/ghB802gZAtuWKAGBv5f+xEhC1+6nSbbuJSaKGUlwrcjacI8fG4dS 6AdXiuR7h7hyDzMNZ0yrAj71KBtOUmj/RM8dn4xuhYDmGVLoICSCQ24QyeZGaEqpc6Ux W6DrYUMTxJLJ2kLpAlGt+e0Rj77Xe19Gd4dRxAmemtln0yYYvo1kqszhHu+EmCLgy9Sv oaMA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20240605; h=errors-to:content-transfer-encoding:list-subscribe:list-help :list-post:list-archive:list-unsubscribe:list-id:precedence:subject :mime-version:references:in-reply-to:message-id:date:to:from :dkim-signature:dkim-signature:dkim-signature; bh=NJJ7SSUXgPZPWidz8gv7DX/PO4qV5SUSiJL0xlvptJ4=; fh=4NbAC/LsuMLI0S0hprUlLSLCiHwg6SCAifhH718Jh0Q=; b=kBGtYEnmQF6hNQk2IaZXDrjkTpKjwX7rqMxLK2EYVoZDEKBqEQXfRyOZcC0vVKGx9K k7Afss18O+e79jv7rBa1AuvWc4Z6H/iv5Ad31u5Ux5tvDE9ei2HgNOj06JY+u3PsX0KV pz7STVAOpsWIh2aRBYg4PsX3gXbryYTgaYVoJbN/3ZQxFFYFUdBPUIoxuAvh0zotcP6U 6kh8S89FfPKFPiFToZdxvEdlam0F36xB8b06iaw6zLqShguPfV7OyW8DmXSVRJLTCZan UgQ0M7bBneknHQkC9B5DOt/QsbOY/rvYPBUIScLOd/oyYa4Fzti5rqrmleGnm2/z0kV+ gj0A==; dara=google.com ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@lists.sourceforge.net header.s=beta header.b=mesUtF6+; dkim=neutral (body hash did not verify) header.i=@sourceforge.net header.s=x header.b=MFtUPHcc; dkim=neutral (body hash did not verify) header.i=@sf.net header.s=x header.b=MzHxmGQG; spf=pass (google.com: domain of openvpn-devel-bounces@lists.sourceforge.net designates 216.105.38.7 as permitted sender) smtp.mailfrom=openvpn-devel-bounces@lists.sourceforge.net; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=muc.de Received: from lists.sourceforge.net (lists.sourceforge.net. [216.105.38.7]) by mx.google.com with ESMTPS id 586e51a60fabf-3f5fe5f6f8asi1001392fac.422.2025.12.12.04.04.15 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Fri, 12 Dec 2025 04:04:15 -0800 (PST) Received-SPF: pass (google.com: domain of openvpn-devel-bounces@lists.sourceforge.net designates 216.105.38.7 as permitted sender) client-ip=216.105.38.7; Authentication-Results: mx.google.com; dkim=pass header.i=@lists.sourceforge.net header.s=beta header.b=mesUtF6+; dkim=neutral (body hash did not verify) header.i=@sourceforge.net header.s=x header.b=MFtUPHcc; dkim=neutral (body hash did not verify) header.i=@sf.net header.s=x header.b=MzHxmGQG; spf=pass (google.com: domain of openvpn-devel-bounces@lists.sourceforge.net designates 216.105.38.7 as permitted sender) smtp.mailfrom=openvpn-devel-bounces@lists.sourceforge.net; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=muc.de DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.sourceforge.net; s=beta; h=Content-Transfer-Encoding:Content-Type: List-Subscribe:List-Help:List-Post:List-Archive:List-Unsubscribe:List-Id: Subject:MIME-Version:References:In-Reply-To:Message-ID:Date:To:From:Sender: Reply-To:Cc:Content-ID:Content-Description:Resent-Date:Resent-From: Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=NJJ7SSUXgPZPWidz8gv7DX/PO4qV5SUSiJL0xlvptJ4=; b=mesUtF6+LhUcY4r9OadViDxH1D dM2TxhDLsSIifkpQWEP2lPzgex4KLEBtEhzREzdF+1sbem4FO2mPlbgHYHO/D1iB2zCgnRnatDdsb 2Yp+K+XJIYKqnxXMnWMQiKPJeaV6hXK81U9di4maXM7KyY4ecuZOeMXMtAdd7dFn3AHo=; Received: from [127.0.0.1] (helo=sfs-ml-2.v29.lw.sourceforge.com) by sfs-ml-2.v29.lw.sourceforge.com with esmtp (Exim 4.95) (envelope-from ) id 1vU1sa-00013Q-97; Fri, 12 Dec 2025 12:04:13 +0000 Received: from [172.30.29.66] (helo=mx.sourceforge.net) by sfs-ml-2.v29.lw.sourceforge.com with esmtps (TLS1.2) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.95) (envelope-from ) id 1vU1sY-00012m-Jm for openvpn-devel@lists.sourceforge.net; Fri, 12 Dec 2025 12:04:11 +0000 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=sourceforge.net; s=x; h=Content-Transfer-Encoding:MIME-Version:References: In-Reply-To:Message-ID:Date:Subject:To:From:Sender:Reply-To:Cc:Content-Type: Content-ID:Content-Description:Resent-Date:Resent-From:Resent-Sender: Resent-To:Resent-Cc:Resent-Message-ID:List-Id:List-Help:List-Unsubscribe: List-Subscribe:List-Post:List-Owner:List-Archive; bh=CCD2b/BDRdcQ5IHbxtSh7kU+N/oMVWzTqDRCo1cV5tY=; b=MFtUPHcc70pFmXxxkDu1BhNHom gggUg5wY5ptOK161dUJPZ4hoi/h4WMeEmlcoppUlNrsldjn0xQ/LFyfliGk5uTSxiUwRlYknwDXOP oRwVhsKYAoAdd/gDVCCZb+QbjmxvBlG8jkIV7/EopMHBLneg0TpAF3KgDTiFunL6G9Sw=; DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=sf.net; s=x ; h=Content-Transfer-Encoding:MIME-Version:References:In-Reply-To:Message-ID: Date:Subject:To:From:Sender:Reply-To:Cc:Content-Type:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Id:List-Help:List-Unsubscribe:List-Subscribe: List-Post:List-Owner:List-Archive; bh=CCD2b/BDRdcQ5IHbxtSh7kU+N/oMVWzTqDRCo1cV5tY=; b=MzHxmGQGOJiFVLZUVK4SPHHEtL drB98pY9lLZZAxj5NDwVZ9kcsk4v0g34Kj8Jz2SYUyx9wGqF19UKsq/R+383BnCz+S0M28ZvcywBw tDD/WycUMsSp4w1rSMSz9pQJlsdLYVCmQGBs11w6YzZSGNMdKjIL+1gstncBL9ahtkPk=; Received: from [193.149.48.134] (helo=blue.greenie.muc.de) by sfi-mx-2.v28.lw.sourceforge.com with esmtps (TLS1.2:ECDHE-RSA-AES256-GCM-SHA384:256) (Exim 4.95) id 1vU1sS-0001Xp-VW for openvpn-devel@lists.sourceforge.net; Fri, 12 Dec 2025 12:04:06 +0000 Received: from blue.greenie.muc.de (localhost [127.0.0.1]) by blue.greenie.muc.de (8.18.1/8.18.1) with ESMTP id 5BCC3rLx017420 for ; Fri, 12 Dec 2025 13:03:53 +0100 Received: (from gert@localhost) by blue.greenie.muc.de (8.18.1/8.18.1/Submit) id 5BCC3qC5017419 for openvpn-devel@lists.sourceforge.net; Fri, 12 Dec 2025 13:03:52 +0100 From: Gert Doering To: openvpn-devel@lists.sourceforge.net Date: Fri, 12 Dec 2025 13:03:46 +0100 Message-ID: <20251212120352.17402-1-gert@greenie.muc.de> X-Mailer: git-send-email 2.51.2 In-Reply-To: References: MIME-Version: 1.0 X-Spam-Score: 1.3 (+) X-Spam-Report: Spam detection software, running on the system "sfi-spamd-1.hosts.colo.sdot.me", has NOT identified this incoming email as spam. The original message has been attached to this so you can view it or label similar future email. If you have any questions, see the administrator of that system for details. Content preview: From: Frank Lichtenheld While fixing the conversion warning I was somewhat confused how this works, so added UTs to verify I understood it. v2: - disable assert test for MS VS - add define for memory-intensive UTs and only enable it by default for CMake builds, so we do not break a lot of builds out there due to memory allocation failures Content analysis details: (1.3 points, 5.0 required) pts rule name description ---- ---------------------- -------------------------------------------------- 1.3 RDNS_NONE Delivered to internal network by a host with no rDNS X-Headers-End: 1vU1sS-0001Xp-VW Subject: [Openvpn-devel] [PATCH v3] mbuf: Add unit tests X-BeenThere: openvpn-devel@lists.sourceforge.net X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: openvpn-devel-bounces@lists.sourceforge.net X-getmail-retrieved-from-mailbox: Inbox X-GMAIL-THRID: =?utf-8?q?1851303978038437936?= X-GMAIL-MSGID: =?utf-8?q?1851303978038437936?= From: Frank Lichtenheld While fixing the conversion warning I was somewhat confused how this works, so added UTs to verify I understood it. v2: - disable assert test for MS VS - add define for memory-intensive UTs and only enable it by default for CMake builds, so we do not break a lot of builds out there due to memory allocation failures Change-Id: Icab68a5fd1b6288955f0073179f1ddde1468d951 Signed-off-by: Frank Lichtenheld Acked-by: Gert Doering Gerrit URL: https://gerrit.openvpn.net/c/openvpn/+/1432 --- This change was reviewed on Gerrit and approved by at least one developer. I request to merge it to master. Gerrit URL: https://gerrit.openvpn.net/c/openvpn/+/1432 This mail reflects revision 3 of this Change. Acked-by according to Gerrit (reflected above): Gert Doering diff --git a/CMakeLists.txt b/CMakeLists.txt index 906fa04..bdb1904 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -633,6 +633,7 @@ endif () endif () +option(UT_ALLOW_BIG_ALLOC "Allow unit-tests to use > 1 GB of memory" ON) if (BUILD_TESTING) find_package(cmocka CONFIG) @@ -649,6 +650,7 @@ "test_buffer" "test_crypto" "test_dhcp" + "test_mbuf" "test_misc" "test_ncp" "test_options_parse" @@ -739,6 +741,9 @@ # for compat with IDEs like Clion that ignore the tests properties # for the environment variable srcdir when running tests as fallback target_compile_definitions(${test_name} PRIVATE "UNIT_TEST_SOURCEDIR=\"${_UT_SOURCE_DIR}\"") + if (UT_ALLOW_BIG_ALLOC) + target_compile_definitions(${test_name} PRIVATE UNIT_TEST_ALLOW_BIG_ALLOC) + endif () if (NOT ${test_name} STREQUAL "test_buffer") target_sources(${test_name} PRIVATE @@ -800,6 +805,12 @@ src/openvpn/xkey_provider.c ) + target_sources(test_mbuf PRIVATE + tests/unit_tests/openvpn/mock_get_random.c + src/openvpn/buffer.c + src/openvpn/mbuf.c + ) + target_sources(test_misc PRIVATE tests/unit_tests/openvpn/mock_get_random.c src/openvpn/options_util.c diff --git a/src/openvpn/mbuf.c b/src/openvpn/mbuf.c index 448124c..42858ec 100644 --- a/src/openvpn/mbuf.c +++ b/src/openvpn/mbuf.c @@ -42,6 +42,8 @@ struct mbuf_set * mbuf_init(unsigned int size) { + ASSERT(size <= MBUF_SIZE_MAX); + struct mbuf_set *ret; ALLOC_OBJ_CLEAR(ret, struct mbuf_set); ret->capacity = adjust_power_of_2(size); @@ -121,6 +123,7 @@ bool ret = false; if (ms) { + ASSERT(item); while (ms->len) { *item = ms->array[ms->head]; diff --git a/src/openvpn/mbuf.h b/src/openvpn/mbuf.h index 7f8c1b7..f741e21 100644 --- a/src/openvpn/mbuf.h +++ b/src/openvpn/mbuf.h @@ -36,6 +36,8 @@ struct multi_instance; #define MBUF_INDEX(head, offset, size) (((head) + (offset)) & ((size) - 1)) +/* limited by adjust_power_of_2 and array_mult_safe */ +#define MBUF_SIZE_MAX (ALLOC_SIZE_MAX / sizeof(struct mbuf_item)) struct mbuf_buffer { diff --git a/src/openvpn/options.c b/src/openvpn/options.c index d01ec47..24c3e92 100644 --- a/src/openvpn/options.c +++ b/src/openvpn/options.c @@ -62,6 +62,7 @@ #include "options_util.h" #include "tun_afunix.h" #include "domain_helper.h" +#include "mbuf.h" #include @@ -7552,7 +7553,7 @@ else if (streq(p[0], "bcast-buffers") && p[1] && !p[2]) { VERIFY_PERMISSION(OPT_P_GENERAL); - atoi_constrained(p[1], &options->n_bcast_buf, p[0], 1, INT_MAX, msglevel); + atoi_constrained(p[1], &options->n_bcast_buf, p[0], 1, MBUF_SIZE_MAX, msglevel); } else if (streq(p[0], "tcp-queue-limit") && p[1] && !p[2]) { diff --git a/tests/unit_tests/openvpn/Makefile.am b/tests/unit_tests/openvpn/Makefile.am index 0f13172..7aeea47 100644 --- a/tests/unit_tests/openvpn/Makefile.am +++ b/tests/unit_tests/openvpn/Makefile.am @@ -6,9 +6,22 @@ AM_TESTS_ENVIRONMENT = export LSAN_OPTIONS=suppressions=$(srcdir)/input/leak_suppr.txt; -test_binaries = argv_testdriver buffer_testdriver crypto_testdriver dhcp_testdriver packet_id_testdriver auth_token_testdriver \ - ncp_testdriver misc_testdriver options_parse_testdriver pkt_testdriver ssl_testdriver \ - user_pass_testdriver push_update_msg_testdriver provider_testdriver socket_testdriver +test_binaries = argv_testdriver \ + auth_token_testdriver \ + buffer_testdriver \ + crypto_testdriver \ + dhcp_testdriver \ + ncp_testdriver \ + mbuf_testdriver \ + misc_testdriver \ + options_parse_testdriver \ + packet_id_testdriver \ + pkt_testdriver \ + provider_testdriver \ + push_update_msg_testdriver \ + socket_testdriver \ + ssl_testdriver \ + user_pass_testdriver if HAVE_LD_WRAP_SUPPORT if !WIN32 @@ -327,6 +340,20 @@ $(top_srcdir)/src/compat/compat-strsep.c \ $(top_srcdir)/src/openvpn/ssl_util.c +mbuf_testdriver_CFLAGS = \ + -I$(top_srcdir)/include -I$(top_srcdir)/src/compat -I$(top_srcdir)/src/openvpn \ + -DSOURCEDIR=\"$(top_srcdir)\" @TEST_CFLAGS@ + +mbuf_testdriver_LDFLAGS = @TEST_LDFLAGS@ + +mbuf_testdriver_SOURCES = test_mbuf.c \ + mock_msg.c test_common.h \ + mock_get_random.c \ + $(top_srcdir)/src/openvpn/buffer.c \ + $(top_srcdir)/src/openvpn/win32-util.c \ + $(top_srcdir)/src/openvpn/platform.c \ + $(top_srcdir)/src/openvpn/mbuf.c + misc_testdriver_CFLAGS = \ -I$(top_srcdir)/include -I$(top_srcdir)/src/compat -I$(top_srcdir)/src/openvpn \ -DSOURCEDIR=\"$(top_srcdir)\" @TEST_CFLAGS@ diff --git a/tests/unit_tests/openvpn/test_buffer.c b/tests/unit_tests/openvpn/test_buffer.c index 25a8def..8855e5b 100644 --- a/tests/unit_tests/openvpn/test_buffer.c +++ b/tests/unit_tests/openvpn/test_buffer.c @@ -386,7 +386,7 @@ /* Instead of trying to trick the compiler here, disable the warnings * for this unit test. We know that the results will be truncated - * and we want to test that. Not we need the clang as clang-cl (msvc) does + * and we want to test that. Note we need the clang as clang-cl (msvc) does * not define __GNUC__ like it does under UNIX(-like) platforms */ #if defined(__GNUC__) || defined(__clang__) /* some clang version do not understand -Wformat-truncation, so ignore the diff --git a/tests/unit_tests/openvpn/test_mbuf.c b/tests/unit_tests/openvpn/test_mbuf.c new file mode 100644 index 0000000..cba4da7 --- /dev/null +++ b/tests/unit_tests/openvpn/test_mbuf.c @@ -0,0 +1,160 @@ +/* + * OpenVPN -- An application to securely tunnel IP networks + * over a single UDP port, with support for SSL/TLS-based + * session authentication and key exchange, + * packet encryption, packet authentication, and + * packet compression. + * + * Copyright (C) 2025 OpenVPN Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, see . + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "syshead.h" + +#include +#include + +#include "buffer.h" +#include "multi.h" +#include "mbuf.h" +#include "test_common.h" + +static void +test_mbuf_init(void **state) +{ + struct mbuf_set *ms = mbuf_init(256); + assert_int_equal(ms->capacity, 256); + assert_false(mbuf_defined(ms)); + assert_non_null(ms->array); + mbuf_free(ms); + + ms = mbuf_init(257); + assert_int_equal(ms->capacity, 512); + mbuf_free(ms); + +#ifdef UNIT_TEST_ALLOW_BIG_ALLOC /* allocates up to 2GB of memory */ + ms = mbuf_init(MBUF_SIZE_MAX); + assert_int_equal(ms->capacity, MBUF_SIZE_MAX); + mbuf_free(ms); + +/* NOTE: expect_assert_failure does not seem to work with MSVC */ +#ifndef _MSC_VER + expect_assert_failure(mbuf_init(MBUF_SIZE_MAX + 1)); +#endif +#endif +} + +static void +test_mbuf_add_remove(void **state) +{ + struct mbuf_set *ms = mbuf_init(4); + assert_int_equal(ms->capacity, 4); + assert_false(mbuf_defined(ms)); + assert_non_null(ms->array); + + /* instances */ + struct multi_instance mi = { 0 }; + struct multi_instance mi2 = { 0 }; + /* buffers */ + struct buffer buf = alloc_buf(16); + struct mbuf_buffer *mbuf_buf = mbuf_alloc_buf(&buf); + assert_int_equal(mbuf_buf->refcount, 1); + struct mbuf_buffer *mbuf_buf2 = mbuf_alloc_buf(&buf); + assert_int_equal(mbuf_buf2->refcount, 1); + free_buf(&buf); + /* items */ + struct mbuf_item mb_item = { .buffer = mbuf_buf, .instance = &mi }; + struct mbuf_item mb_item2 = { .buffer = mbuf_buf2, .instance = &mi2 }; + + mbuf_add_item(ms, &mb_item); + assert_int_equal(mbuf_buf->refcount, 2); + assert_int_equal(mbuf_buf2->refcount, 1); + assert_int_equal(mbuf_len(ms), 1); + assert_int_equal(mbuf_maximum_queued(ms), 1); + assert_int_equal(ms->head, 0); + assert_ptr_equal(mbuf_peek(ms), &mi); + + mbuf_add_item(ms, &mb_item2); + assert_int_equal(mbuf_buf->refcount, 2); + assert_int_equal(mbuf_buf2->refcount, 2); + assert_int_equal(mbuf_len(ms), 2); + assert_int_equal(mbuf_maximum_queued(ms), 2); + assert_int_equal(ms->head, 0); + assert_ptr_equal(mbuf_peek(ms), &mi); + + mbuf_add_item(ms, &mb_item2); + assert_int_equal(mbuf_buf->refcount, 2); + assert_int_equal(mbuf_buf2->refcount, 3); + assert_int_equal(mbuf_len(ms), 3); + assert_int_equal(mbuf_maximum_queued(ms), 3); + assert_int_equal(ms->head, 0); + assert_ptr_equal(mbuf_peek(ms), &mi); + + mbuf_add_item(ms, &mb_item2); + mbuf_add_item(ms, &mb_item2); /* overflow, first item gets removed */ + assert_int_equal(mbuf_buf->refcount, 1); + assert_int_equal(mbuf_buf2->refcount, 5); + assert_int_equal(mbuf_len(ms), 4); + assert_int_equal(mbuf_maximum_queued(ms), 4); + assert_int_equal(ms->head, 1); + assert_ptr_equal(mbuf_peek(ms), &mi2); + + mbuf_add_item(ms, &mb_item); + assert_int_equal(mbuf_buf->refcount, 2); + assert_int_equal(mbuf_buf2->refcount, 4); + assert_int_equal(mbuf_len(ms), 4); + assert_int_equal(mbuf_maximum_queued(ms), 4); + assert_int_equal(ms->head, 2); + assert_ptr_equal(mbuf_peek(ms), &mi2); + + struct mbuf_item out_item; + assert_true(mbuf_extract_item(ms, &out_item)); + assert_ptr_equal(out_item.instance, mb_item2.instance); + assert_int_equal(mbuf_buf->refcount, 2); + assert_int_equal(mbuf_buf2->refcount, 4); + assert_int_equal(mbuf_len(ms), 3); + assert_int_equal(mbuf_maximum_queued(ms), 4); + assert_int_equal(ms->head, 3); + assert_ptr_equal(mbuf_peek(ms), &mi2); + mbuf_free_buf(out_item.buffer); + + mbuf_dereference_instance(ms, &mi2); + assert_int_equal(mbuf_buf->refcount, 2); + assert_int_equal(mbuf_buf2->refcount, 1); + assert_int_equal(mbuf_len(ms), 3); + assert_int_equal(mbuf_maximum_queued(ms), 4); + assert_int_equal(ms->head, 3); + assert_ptr_equal(mbuf_peek(ms), &mi); + + mbuf_free(ms); + assert_int_equal(mbuf_buf->refcount, 1); + mbuf_free_buf(mbuf_buf); + assert_int_equal(mbuf_buf2->refcount, 1); + mbuf_free_buf(mbuf_buf2); +} + +int +main(void) +{ + const struct CMUnitTest tests[] = { + cmocka_unit_test(test_mbuf_init), + cmocka_unit_test(test_mbuf_add_remove), + }; + + return cmocka_run_group_tests_name("mbuf", tests, NULL, NULL); +}