Skip to content
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

tests: Fix tools::is_hdd unit tests #9716

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
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 .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,8 @@ jobs:
run: sudo ${{env.APT_INSTALL_LINUX}}
- name: install Python dependencies
run: pip install requests psutil monotonic zmq deepdiff
- name: create dummy disk drives for testing
run: tests/create_test_disks.sh >> $GITHUB_ENV
- name: tests
env:
CTEST_OUTPUT_ON_FAILURE: ON
Expand Down
90 changes: 90 additions & 0 deletions tests/create_test_disks.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
#!/bin/bash

set -e

LOOP_DEVICE_MAJOR=7
LOOP_DEVICE_MIN_ID=100

echo_err() {
echo "$@" >&2
}

create_device_node() {
local -r last_id=$(find /dev/ -name 'loop[0-9]*' | sed 's/^.*loop//' | sort -r -n | head -1)
local id=$((last_id + 1))
if [[ "$id" -lt "$LOOP_DEVICE_MIN_ID" ]]; then
id="$LOOP_DEVICE_MIN_ID"
fi
local path
for (( i=0; i<10; i++ )); do
path="/dev/loop$id"
if [[ ! -e "$path" ]] && sudo mknod "$path" b "$LOOP_DEVICE_MAJOR" "$id"; then
echo "$path"
return 0
fi
$((id++))
done
return 1
}

device_mountpoint() {
local -r datadir="$1"
local -r dev="$2"
if [[ -z "$datadir" || -z "$dev" ]]; then
echo_err "Usage: device_mountpoint <data dir> <device>"
return 1
fi
echo "$datadir/mnt-$(basename "$dev")"
}

create_device() {
local -r datadir="$1"
if [[ -z "$datadir" ]]; then
echo_err "Usage: create_device <data dir>"
return 1
fi
local -r dev=$(create_device_node)
local -r fs="$datadir/$(basename "$dev").vhd"
local -r mountpoint=$(device_mountpoint "$datadir" "$dev")
echo_err
echo_err "# Device $dev"
dd if=/dev/zero of="$fs" bs=64K count=128 >/dev/null 2>&1
sudo losetup "$dev" "$fs"
sudo mkfs.ext4 "$dev" >/dev/null 2>&1
mkdir "$mountpoint"
sudo mount "$dev" "$mountpoint"
echo "$dev"
}

# Unused by default, but helpful for local development
destroy_device() {
local -r datadir="$1"
local -r dev="$2"
if [[ -z "$datadir" || -z "$dev" ]]; then
echo_err "Usage: destroy_device <data dir> <device>"
return 1
fi
echo_err "Destroying device $dev"
sudo umount $(device_mountpoint "$datadir" "$dev")
sudo losetup -d "$dev"
sudo rm "$dev"
}

block_device_path() {
device_name=$(basename "$1")
device_minor=${device_name/#loop}
echo "/sys/dev/block/$LOOP_DEVICE_MAJOR:$device_minor"
}

tmpdir=$(mktemp --tmpdir -d monerotest.XXXXXXXX)
echo_err "Creating devices using temporary directory: $tmpdir"

dev_rot=$(create_device "$tmpdir")
bdev_rot=$(block_device_path "$dev_rot")
echo 1 | sudo tee "$bdev_rot/queue/rotational" >/dev/null
echo MONERO_TEST_DEVICE_HDD=$(device_mountpoint "$tmpdir" "$dev_rot")

dev_ssd=$(create_device "$tmpdir")
bdev_ssd=$(block_device_path "$dev_ssd")
echo 0 | sudo tee "$bdev_ssd/queue/rotational" >/dev/null
echo MONERO_TEST_DEVICE_SSD=$(device_mountpoint "$tmpdir" "$dev_ssd")
37 changes: 28 additions & 9 deletions tests/unit_tests/is_hdd.cpp
Original file line number Diff line number Diff line change
@@ -1,17 +1,36 @@
#include "common/util.h"
#include <cstdlib>
#include <string>
#include <gtest/gtest.h>
#include <boost/optional/optional_io.hpp> /* required to output boost::optional in assertions */

#ifndef GTEST_SKIP
#include <iostream>
#define SKIP_TEST(reason) do {std::cerr << "Skipping test: " << reason << std::endl; return;} while(0)
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I introduced this macro because GTEST_SKIP doesn't exist in fairly old versions of gtest (e.g. the vendored one, as well as the default installs on Debian 10 and Ubuntu 20), but should be available on every build in the near future, at which point I'll drop the macro.

Copy link
Author

@iamamyth iamamyth Jan 18, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Link to the PR which introduced GTEST_SKIP: google/googletest#1544. As best as I can tell, it landed in the 1.10.0 release, dated 2019-10-03.

#else
#define SKIP_TEST(reason) GTEST_SKIP() << reason
#endif

#if defined(__GLIBC__)
TEST(is_hdd, linux_os_root)
{
std::string path = "/";
EXPECT_TRUE(tools::is_hdd(path.c_str()) != boost::none);
TEST(is_hdd, rotational_drive) {
const char *hdd = std::getenv("MONERO_TEST_DEVICE_HDD");
if (hdd == nullptr)
SKIP_TEST("No rotational disk device configured");
EXPECT_EQ(tools::is_hdd(hdd), boost::optional<bool>(true));
}
#else
TEST(is_hdd, unknown_os)
{
std::string path = "";
EXPECT_FALSE(tools::is_hdd(path.c_str()) != boost::none);

TEST(is_hdd, ssd) {
const char *ssd = std::getenv("MONERO_TEST_DEVICE_SSD");
if (ssd == nullptr)
SKIP_TEST("No SSD device configured");
EXPECT_EQ(tools::is_hdd(ssd), boost::optional<bool>(false));
}

TEST(is_hdd, unknown_attrs) {
EXPECT_EQ(tools::is_hdd("/dev/null"), boost::none);
}
#endif
TEST(is_hdd, stability)
{
EXPECT_NO_THROW(tools::is_hdd(""));
}
Loading