Skip to content

Instantly share code, notes, and snippets.

@lfyuomr-gylo
Last active February 4, 2020 18:47
Show Gist options
  • Save lfyuomr-gylo/2286c5eddf4385a4ae311c230078c5b6 to your computer and use it in GitHub Desktop.
Save lfyuomr-gylo/2286c5eddf4385a4ae311c230078c5b6 to your computer and use it in GitHub Desktop.
Minimal project to demonstrate the problem with open file descriptors when tests are launched via ctest

Run the following commands:

mkdir build
cd build
cmake ..
make

Then, there are two different ways to run tests:

  1. Via CTest:
ctest --verbose
  1. Manually run test executable
./test_list_open_file_descriptors

In case of manual execution test passes successfully, but when it's launched via ctest command, it fails with the following error:

1: Expected equality of these values:
1:   actual_file_descriptors
1:     Which is: { 3, 2, 0, 1 }
1:   expected_file_descriptors
1:     Which is: { 2, 1, 0 }
1
cmake_minimum_required(VERSION 3.15)
project(ctest_file_descriptors_problem_demo)
set(CMAKE_CXX_STANDARD 17)
add_library(list_open_file_descriptors list_open_file_descriptors.cpp)
include(FetchContent)
FetchContent_Declare(
googletest
GIT_REPOSITORY https://github.com/google/googletest.git
GIT_TAG release-1.10.0
)
FetchContent_MakeAvailable(googletest)
enable_testing()
include(GoogleTest)
add_executable(test_list_open_file_descriptors test_list_open_file_descriptors.cpp)
target_link_libraries(test_list_open_file_descriptors list_open_file_descriptors gtest_main)
gtest_discover_tests(test_list_open_file_descriptors)
#include "list_open_file_descriptors.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <dirent.h>
#include <unistd.h>
void DiscoverOpenFileDescriptors(std::unordered_set<int> *out_file_descriptors) {
int dirfd = open("/dev/fd", O_RDONLY);
DIR *dir = fdopendir(dirfd);
for (dirent *entry = readdir(dir); entry; entry = readdir(dir)) {
const std::string entry_name = entry->d_name;
if (entry_name == "." || entry_name == "..") {
continue;
}
const int fd = std::atoi(entry->d_name);
if (fd != dirfd) {
out_file_descriptors->insert(fd);
}
}
closedir(dir);
close(dirfd);
}
#ifndef CTEST_FILE_DESCRIPTORS_PROBLEM_DEMO__LIST_OPEN_FILE_DESCRIPTORS_H_
#define CTEST_FILE_DESCRIPTORS_PROBLEM_DEMO__LIST_OPEN_FILE_DESCRIPTORS_H_
#include <unordered_set>
void DiscoverOpenFileDescriptors(std::unordered_set<int> *out_file_descriptors);
#endif //CTEST_FILE_DESCRIPTORS_PROBLEM_DEMO__LIST_OPEN_FILE_DESCRIPTORS_H_
#include "list_open_file_descriptors.h"
#include <gtest/gtest.h>
TEST(OpenFileDescriptorsTest, OnlyStdinStdoutAndStderrShouldBeDetectedIfNoFilesAreOpen) {
std::unordered_set<int> actual_file_descriptors;
DiscoverOpenFileDescriptors(&actual_file_descriptors);
std::unordered_set<int> expected_file_descriptors{0, 1, 2};
ASSERT_EQ(actual_file_descriptors, expected_file_descriptors);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment