Source
stdlib/tests/os_test.cpp
1
// Copyright (c) 2026 BigBrain LLC. MIT-licensed (see LICENSE).2
// Original work; see ACKNOWLEDGMENTS.md for the open-source ideas we build upon.3
#include "os.hpp"5
#include <fstream>6
#include <stdexcept>7
#include <string>8
#include <string_view>9
#include <utility>10
#include <vector>12
#include <gtest/gtest.h>14
namespace os = cheatah::os;16
// The os.path.join concept must accept string-constructible types and reject the17
// rest, without narrowing today's accepted set.18
static_assert(os::StringLike<const char*>);19
static_assert(os::StringLike<std::string>);20
static_assert(os::StringLike<std::string_view>);21
static_assert(!os::StringLike<int>);23
TEST(CheatahOs, PathJoin) {24
EXPECT_EQ(os::path::join("a", "b", "c"), "a/b/c");25
EXPECT_EQ(os::path::join("only"), "only");26
}28
TEST(CheatahOs, PathSplitext) {29
const auto [root, ext] = os::path::splitext("dir/file.purr");30
EXPECT_EQ(root, "dir/file");31
EXPECT_EQ(ext, ".purr");32
const auto [root2, ext2] = os::path::splitext("noext");33
EXPECT_EQ(root2, "noext");34
EXPECT_EQ(ext2, "");35
}37
TEST(CheatahOs, PathBasenameDirname) {38
EXPECT_EQ(os::path::basename("a/b/c.txt"), "c.txt");39
EXPECT_EQ(os::path::dirname("a/b/c.txt"), "a/b");40
}42
TEST(CheatahOs, CwdAndCpuCount) {43
EXPECT_FALSE(os::getcwd().empty());44
EXPECT_GT(os::cpu_count(), 0u);45
}47
TEST(CheatahOs, GetenvFallback) {48
EXPECT_EQ(os::getenv("CHEATAH_NONEXISTENT_VAR_xyz", "fallback"), "fallback");49
}51
TEST(CheatahOs, SetenvThenGetenv) {52
os::setenv("CHEATAH_PURR_TEST_VAR", "meow");53
EXPECT_EQ(os::getenv("CHEATAH_PURR_TEST_VAR"), "meow");54
}56
TEST(CheatahOs, MakeDirExistsThenRemove) {57
const std::string dir = "purr_os_tmpdir";58
os::remove(dir); // start clean59
os::mkdir(dir);60
EXPECT_TRUE(os::path::exists(dir));61
EXPECT_TRUE(os::path::isdir(dir));62
os::rmdir(dir);63
EXPECT_FALSE(os::path::exists(dir));64
}66
TEST(CheatahOs, FileQueriesIsfileAndGetsize) {67
const std::string f = "purr_os_file.txt";68
{ std::ofstream o(f); o << "12345"; }69
EXPECT_TRUE(os::path::exists(f));70
EXPECT_TRUE(os::path::isfile(f));71
EXPECT_FALSE(os::path::isdir(f));72
EXPECT_EQ(os::path::getsize(f), 5u);73
EXPECT_TRUE(os::remove(f));74
EXPECT_FALSE(os::path::exists(f));75
}77
TEST(CheatahOs, AbspathAndNormpath) {78
EXPECT_EQ(os::path::normpath("a/./b/../c"), "a/c");79
const std::string ap = os::path::abspath("x");80
ASSERT_FALSE(ap.empty());81
EXPECT_EQ(ap.front(), '/'); // absolute path82
}84
TEST(CheatahOs, MakedirsAndChdir) {85
const std::string nested = "purr_os_a/b/c";86
os::makedirs(nested);87
EXPECT_TRUE(os::path::isdir(nested));88
const std::string cwd = os::getcwd();89
os::chdir("purr_os_a");90
EXPECT_NE(os::getcwd(), cwd);91
os::chdir(cwd); // restore92
EXPECT_EQ(os::getcwd(), cwd);93
os::rmdir("purr_os_a/b/c");94
os::rmdir("purr_os_a/b");95
os::rmdir("purr_os_a");96
EXPECT_FALSE(os::path::exists("purr_os_a"));97
}99
TEST(CheatahOs, ListdirAndRename) {100
const std::string dir = "purr_os_list";101
os::remove(dir);102
os::mkdir(dir);103
{ std::ofstream o(dir + "/one.txt"); o << "x"; }104
const std::vector<std::string> entries = os::listdir(dir);105
ASSERT_EQ(entries.size(), 1u);106
EXPECT_EQ(entries[0], "one.txt"); // listdir returns basenames107
os::rename(dir + "/one.txt", dir + "/two.txt");108
EXPECT_TRUE(os::path::isfile(dir + "/two.txt"));109
EXPECT_FALSE(os::path::isfile(dir + "/one.txt"));110
os::remove(dir + "/two.txt");111
os::rmdir(dir);112
}114
TEST(CheatahOs, PidAndSystem) {115
EXPECT_GT(os::getpid(), 0);116
EXPECT_EQ(os::system("true"), 0);117
EXPECT_NE(os::system("false"), 0);118
}120
TEST(CheatahOs, Urandom) {121
EXPECT_EQ(os::urandom(0).size(), 0u);122
EXPECT_EQ(os::urandom(32).size(), 32u);123
// A request larger than one getentropy() chunk (256 bytes) must still be filled.124
EXPECT_EQ(os::urandom(300).size(), 300u);125
// Two draws of real entropy are astronomically unlikely to collide.126
EXPECT_NE(os::urandom(32), os::urandom(32));127
EXPECT_THROW(os::urandom(-1), std::invalid_argument);128
}130
TEST(CheatahOs, ModuleExt) {131
// Exactly the platform's loadable-module extension, leading dot included.132
const std::string ext = os::module_ext();133
#if defined(_WIN32)134
EXPECT_EQ(ext, ".dll");135
#elif defined(__APPLE__)136
EXPECT_EQ(ext, ".dylib");137
#else138
EXPECT_EQ(ext, ".so");139
#endif140
}