Skip to content

Added missing virtual destructors #218

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Added unit test for virtual destructors
The purpose of this tests is to hihglight the need for a virtual
destructor through valgrind unit test execution
  • Loading branch information
andreagilardoni committed Feb 19, 2025
commit 5046281cc6807e493eaeb2f49fc0b9d4beea217d
1 change: 1 addition & 0 deletions test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ set(TEST_SRCS
src/WCharacter/test_isUpperCase.cpp
src/WCharacter/test_isWhitespace.cpp
src/WCharacter/test_toAscii.cpp
src/Interfaces/test_virtualDestructor.cpp
)

set(TEST_DUT_SRCS
Expand Down
45 changes: 45 additions & 0 deletions test/include/TCPClientMock.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/*
* Copyright (c) 2020 Arduino. All rights reserved.
*
* SPDX-License-Identifier: LGPL-2.1-or-later
*/

#ifndef TCPCLIENT_MOCK_H_
#define TCPCLIENT_MOCK_H_

/**************************************************************************************
* INCLUDE
**************************************************************************************/

#include <api/Client.h>

/**************************************************************************************
* CLASS DECLARATION
**************************************************************************************/

/*
* The purpose of this class is currently to highlight the effects of lacking virtual destructor
*/

#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-parameter"

class TCPClientMock : public arduino::Client {
public:
virtual int connect(IPAddress ip, uint16_t port) { return 0; }
virtual int connect(const char *host, uint16_t port) { return 0; }
virtual size_t write(uint8_t) { return 0; }
virtual size_t write(const uint8_t *buf, size_t size) { return 0;}
virtual int available() { return 0; }
virtual int read() { return 0; }
virtual int read(uint8_t *buf, size_t size) { return 0;}
virtual int peek() { return 0; }
virtual void flush() {}
virtual void stop() {}
virtual uint8_t connected() { return 0;}
virtual operator bool() { return true; }
};
#pragma GCC diagnostic pop


#endif /* TCPCLIENT_MOCK_H_ */
36 changes: 36 additions & 0 deletions test/src/Interfaces/test_virtualDestructor.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/*
* Copyright (c) 2020 Arduino. All rights reserved.
*
* SPDX-License-Identifier: LGPL-2.1-or-later
*/

#include <catch2/catch_test_macros.hpp>
#include <api/IPAddress.h>
#include <TCPClientMock.h>

/*
* The purpose of these tests is to highlight potential memory leaking
* issues that may arise from the lack of virtual destructors.
* These test cases will never fail under unit testing,
* but they should trigger valgrind error reporting
*/

TEST_CASE("Testing polymorphic IPAddress memory free", "[ipaddress-delete-01]")
{
arduino::Printable* p = new IPAddress();

#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdelete-non-virtual-dtor"
delete p;
#pragma GCC diagnostic pop
}

TEST_CASE("Testing polymorphic client memory free", "[client-delete-01]")
{
arduino::Client* p = new TCPClientMock;

#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdelete-non-virtual-dtor"
delete p;
#pragma GCC diagnostic pop
}
24 changes: 24 additions & 0 deletions virtual_destructors_testing/benchmark.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
#!/bin/bash

FQBNS=(
arduino-git:renesas_portenta_main:unor4wifi
# arduino-git:mbed:envie_m7
# arduino-git:avr:uno
# arduino-git:samd:mkrwifi1010
# arduino-git:mbed:opta
)

branches=(
master
virtual-destructors
)

for branch in "${branches[@]}"; do
git checkout $branch
for fqbn in $"${FQBNS[@]}"; do
echo "compiling for " $fqbn.$branch
# arduino-cli compile -b $fqbn | tee $fqbn.$branch.log
arduino-cli compile -b $fqbn --build-property "compiler.cpp.extra_flags=\"-fdump-record-layouts\""
# /home/agilardoni/.arduino15/packages/arduino/tools/arm-none-eabi-gcc/7-2017q4/bin/arm-none-eabi-size -A /tmp/arduino/sketches/97A7C8915D2115841AF9E1023FFD9539/virtual_destructors_testing.ino.elf | tee $fqbn.$branch.size.log
done
done
55 changes: 55 additions & 0 deletions virtual_destructors_testing/virtual_destructors_testing.ino
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@

#if defined(ARDUINO_SAMD_MKR1000)
#include <WiFi101.h>
#include <WiFiUdp.h>
#elif defined(ARDUINO_SAMD_MKRWIFI1010) || defined(ARDUINO_SAMD_NANO_33_IOT) || defined(ARDUINO_AVR_UNO_WIFI_REV2) || defined (ARDUINO_NANO_RP2040_CONNECT)
#include <WiFiNINA.h>
#include <WiFiUdp.h>
#elif defined(ARDUINO_PORTENTA_H7_M7) || defined(ARDUINO_PORTENTA_H7_M7) || \
defined(ARDUINO_NICLA_VISION) || defined(ARDUINO_OPTA) || defined(ARDUINO_GIGA)
#include <WiFi.h>
#include <WiFiUdp.h>
#elif defined(ARDUINO_PORTENTA_C33)
#include <WiFiC3.h>
#include <WiFiUdp.h>
#elif defined(ARDUINO_ARCH_ESP8266)
#include <ESP8266WiFi.h>
#include <WiFiUdp.h>
#elif defined(ARDUINO_ARCH_ESP32)
#include <WiFi.h>
#include <WiFiUdp.h>
#elif defined(ARDUINO_UNOR4_WIFI)
#include <WiFiS3.h>
#elif defined(ARDUINO_RASPBERRY_PI_PICO_W)
#include <WiFi.h>
#include <WiFiUdp.h>
#endif
void setup() {
Serial.begin(115200);

while(!Serial);

Serial.println("Hello world");

#if defined(ARDUINO_SAMD_MKR1000) || \
defined(ARDUINO_SAMD_MKRWIFI1010) || \
defined(ARDUINO_SAMD_NANO_33_IOT) || \
defined(ARDUINO_AVR_UNO_WIFI_REV2) || \
defined(ARDUINO_NANO_RP2040_CONNECT) || \
defined(ARDUINO_PORTENTA_H7_M7) || \
defined(ARDUINO_PORTENTA_H7_M7) || \
defined(ARDUINO_NICLA_VISION) || \
defined(ARDUINO_OPTA) || \
defined(ARDUINO_GIGA) || \
defined(ARDUINO_PORTENTA_C33) || \
defined(ARDUINO_ARCH_ESP8266) || \
defined(ARDUINO_ARCH_ESP32) || \
defined(ARDUINO_UNOR4_WIFI) || \
defined(ARDUINO_RASPBERRY_PI_PICO_W)
Client *c = new WiFiClient(); // sizeof // as global variable
delete c;
#endif
}

void loop() {
}