Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
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
2 changes: 2 additions & 0 deletions api/Print.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ class Print
void setWriteError(int err = 1) { write_error = err; }
public:
Print() : write_error(0) {}
virtual ~Print() {}


int getWriteError() { return write_error; }
void clearWriteError() { setWriteError(0); }
Expand Down
1 change: 1 addition & 0 deletions api/Printable.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ class Print;
class Printable
{
public:
virtual ~Printable() {}
virtual size_t printTo(Print& p) const = 0;
};

Expand Down
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
}
4 changes: 2 additions & 2 deletions test/src/String/test_characterAccessFunc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -55,14 +55,14 @@ TEST_CASE ("Testing String::getBytes(unsigned char, unsigned int, unsigned int)"
}
}

TEST_CASE ("Testing & String::operator[]", "[String-&operator[]-03]")
TEST_CASE ("Testing & String::operator[]", "[String-&operator subscript-03]")
{
arduino::String str("Hello");
str[0] = 'M';
REQUIRE(str == "Mello");
}

TEST_CASE ("Testing & String::operator[] with invalid buffer", "[String-&operator[]-04]")
TEST_CASE ("Testing & String::operator[] with invalid buffer", "[String-&operator subscript-04]")
{
char *buffer = NULL;
arduino::String str(buffer);
Expand Down
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() {
}
Loading