WSL/test/linux/unit_tests/sysfs.c
WSL Team 697572d664 Initial open source commit for WSL.
Many Microsoft employees have contributed to the Windows Subsystem for Linux, this commit is the result of their work since 2016.

The entire history of the Windows Subsystem for Linux can't be shared here, but here's an overview of WSL's history after it moved to it own repository in 2021:

Number of commits on the main branch: 2930
Number of contributors: 31

Head over https://github.com/microsoft/WSL/releases for a more detailed history of the features added to WSL since 2021.
2025-05-15 12:09:45 -07:00

391 lines
9.3 KiB
C

/*++
Copyright (c) Microsoft. All rights reserved.
Module Name:
sysfs.c
Abstract:
This file contains tests for the sysfs file system.
--*/
#include "lxtcommon.h"
#include "unittests.h"
#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>
#include <fcntl.h>
#define LXT_NAME "SysFs"
#define SYSFS_MNT "/sys"
int SysFsClassNet(PLXT_ARGS Args);
int SysFsDevicesSystemCpu(PLXT_ARGS Args);
int SysFsDevicesVirtualNet(PLXT_ARGS Args);
int SysFsKernelDebug(PLXT_ARGS Args);
int SysFsRoot(PLXT_ARGS Args);
//
// Global constants
//
static const LXT_VARIATION g_LxtVariations[] = {
{"SysFs - /sys root", SysFsRoot},
{"SysFs - /sys/class/net", SysFsClassNet},
{"SysFs - /sys/devices/virtual/net", SysFsDevicesVirtualNet},
{"SysFs - /sys/devices/system/cpu", SysFsDevicesSystemCpu},
{"SysFs - /sys/kernel/debug", SysFsKernelDebug},
};
static const LXT_CHILD_INFO g_SysFsRootChildren[] = {
{"block", DT_DIR},
{"bus", DT_DIR},
{"class", DT_DIR},
{"dev", DT_DIR},
{"devices", DT_DIR},
{"firmware", DT_DIR},
{"fs", DT_DIR},
{"kernel", DT_DIR},
{"module", DT_DIR},
{"power", DT_DIR}};
static const LXT_CHILD_INFO g_SysFsClassNetChildren[] = {{"lo", DT_LNK}};
static const LXT_CHILD_INFO g_SysFsDevicesVirtualNetChildren[] = {{"lo", DT_DIR}};
static const LXT_CHILD_INFO g_SysFsDevicesVirtualNetDeviceChildren[] = {
{"address", DT_REG}, {"ifindex", DT_REG}, {"flags", DT_REG}, {"mtu", DT_REG}};
static const LXT_CHILD_INFO g_SysFsDevicesSystemCpuChildren[] = {{"cpu0", DT_DIR}, {"present", DT_REG}, {"possible", DT_REG}};
static const LXT_CHILD_INFO g_SysFsDevicesSystemCpuDeviceChildren[] = {{"topology", DT_DIR}};
static const LXT_CHILD_INFO g_SysFsDevicesSystemCpuDeviceCpuFreqChildren[] = {{"cpuinfo_max_freq", DT_REG}, {"scaling_max_freq", DT_REG}};
static const LXT_CHILD_INFO g_SysFsDevicesSystemCpuDeviceTopologyChildren[] = {
{"core_id", DT_REG},
{"core_siblings", DT_REG},
{"core_siblings_list", DT_REG},
{"physical_package_id", DT_REG},
{"thread_siblings", DT_REG},
{"thread_siblings_list", DT_REG}};
static const LXT_CHILD_INFO g_SysFsKernelDebugChildren[] = {{"tracing", DT_DIR}, {"wakeup_sources", DT_REG}};
static const LXT_CHILD_INFO g_SysFsKernelDebugTracingChildren[] = {{"trace_marker", DT_REG}};
static const LXT_CHILD_INFO g_SysFsKernelIp4Children[] = {
{"tcp_rmem_min", DT_REG}, {"tcp_rmem_def", DT_REG}, {"tcp_rmem_max", DT_REG}, {"tcp_wmem_min", DT_REG}, {"tcp_wmem_def", DT_REG}, {"tcp_wmem_max", DT_REG}};
static const LXT_CHILD_INFO g_SysFsModuleLowmemorykillerChildren[] = {{"parameters", DT_DIR}};
static const LXT_CHILD_INFO g_SysFsModuleLowmemorykillerParametersChildren[] = {{"adj", DT_REG}, {"minfree", DT_REG}};
static const LXT_CHILD_INFO g_SysFsPowerChildren[] = {{"autosleep", DT_REG}};
int SysfsTestEntry(int Argc, char* Argv[])
/*++
Routine Description:
This routine is the main entry point for the procfs tests.
Arguments:
Argc - Supplies the number of command line arguments.
Argv - Supplies the command line arguments.
Return Value:
Returns 0 on success, -1 on failure.
--*/
{
LXT_ARGS Args;
int Result;
LxtCheckResult(LxtInitialize(Argc, Argv, &Args, LXT_NAME));
LxtCheckResult(LxtRunVariations(&Args, g_LxtVariations, LXT_COUNT_OF(g_LxtVariations)));
ErrorExit:
LxtUninitialize();
return !LXT_SUCCESS(Result);
}
int SysFsClassNet(PLXT_ARGS Args)
/*++
Description:
This routine tests the sysfs network class directory (/sys/class/net).
Arguments:
Args - Supplies the command line arguments.
Return Value:
Returns 0 on success, -1 on failure.
--*/
{
int Result;
//
// This test may fail on real Linux because the contents are not
// guaranteed to be the same on every system.
//
LxtCheckResult(LxtCheckDirectoryContents(SYSFS_MNT "/class/net", g_SysFsClassNetChildren, LXT_COUNT_OF(g_SysFsClassNetChildren)));
LxtCheckResult(LxtCheckLinkTarget(SYSFS_MNT "/class/net/lo", "../../devices/virtual/net/lo"));
ErrorExit:
return Result;
}
int SysFsDevicesSystemCpu(PLXT_ARGS Args)
/*++
Description:
This routine tests the cpu device directory (/sys/devices/system/cpu).
Arguments:
Args - Supplies the command line arguments.
Return Value:
Returns 0 on success, -1 on failure.
--*/
{
char Buffer[100];
char ChildPath[256];
int CpuInfoProcessorCount;
ssize_t BytesRead;
int Fd;
char* Line;
int ProcessorIndex;
int ProcessorCount;
int Result;
size_t Size;
FILE* Stream;
//
// First check always present contents.
//
Fd = 0;
Stream = NULL;
Line = NULL;
LxtCheckResult(LxtCheckDirectoryContents(
SYSFS_MNT "/devices/system/cpu", g_SysFsDevicesSystemCpuChildren, LXT_COUNT_OF(g_SysFsDevicesSystemCpuChildren)));
//
// Determine the number of CPUs.
//
LxtCheckErrno(Fd = open(SYSFS_MNT "/devices/system/cpu/present", O_RDONLY));
LxtCheckErrno(BytesRead = read(Fd, Buffer, sizeof(Buffer)));
LxtCheckEqual(Buffer[0], '0', "%c");
ProcessorCount = 1;
if (Buffer[1] != '\n')
{
LxtCheckEqual(Buffer[1], '-', "%c");
ProcessorCount = strtol(&Buffer[2], NULL, 10);
LxtCheckGreater(ProcessorCount, 0, "%d");
ProcessorCount += 1;
}
LxtCheckErrnoZeroSuccess(close(Fd));
//
// Check CPU directory for each CPU.
//
for (ProcessorIndex = 0; ProcessorIndex < ProcessorCount; ProcessorIndex += 1)
{
snprintf(ChildPath, sizeof(ChildPath), SYSFS_MNT "/devices/system/cpu/cpu%d", ProcessorIndex);
LxtCheckResult(LxtCheckDirectoryContents(
ChildPath, g_SysFsDevicesSystemCpuDeviceChildren, LXT_COUNT_OF(g_SysFsDevicesSystemCpuDeviceChildren)));
snprintf(ChildPath, sizeof(ChildPath), SYSFS_MNT "/devices/system/cpu/cpu%d/topology", ProcessorIndex);
LxtCheckResult(LxtCheckDirectoryContents(
ChildPath, g_SysFsDevicesSystemCpuDeviceTopologyChildren, LXT_COUNT_OF(g_SysFsDevicesSystemCpuDeviceTopologyChildren)));
}
//
// No more directories should exist.
//
snprintf(ChildPath, sizeof(ChildPath), SYSFS_MNT "/devices/system/cpu/cpu%d", ProcessorCount);
LxtCheckErrnoFailure(open(ChildPath, O_RDONLY | O_DIRECTORY), ENOENT);
//
// Check if the number of CPUs matches /proc/cpuinfo.
//
Stream = fopen("/proc/cpuinfo", "r");
if (Stream == NULL)
{
LxtLogError("fopen failed, errno: %d", errno);
Result = LXT_RESULT_FAILURE;
goto ErrorExit;
}
Size = 0;
CpuInfoProcessorCount = 0;
while (getline(&Line, &Size, Stream) != -1)
{
if (strstr(Line, "processor") == Line)
{
CpuInfoProcessorCount += 1;
}
}
LxtCheckEqual(ProcessorCount, CpuInfoProcessorCount, "%d");
ErrorExit:
if (Line != NULL)
{
free(Line);
}
if (Stream != NULL)
{
fclose(Stream);
}
if (Fd > 0)
{
close(Fd);
}
return Result;
}
int SysFsDevicesVirtualNet(PLXT_ARGS Args)
/*++
Description:
This routine tests the sysfs network device directory
(/sys/devices/virtual/net).
Arguments:
Args - Supplies the command line arguments.
Return Value:
Returns 0 on success, -1 on failure.
--*/
{
int Result;
//
// This test may fail on real Linux because the contents are not
// guaranteed to be the same on every system.
//
LxtCheckResult(LxtCheckDirectoryContents(
SYSFS_MNT "/devices/virtual/net", g_SysFsDevicesVirtualNetChildren, LXT_COUNT_OF(g_SysFsDevicesVirtualNetChildren)));
LxtCheckResult(LxtCheckDirectoryContents(
SYSFS_MNT "/devices/virtual/net/lo", g_SysFsDevicesVirtualNetDeviceChildren, LXT_COUNT_OF(g_SysFsDevicesVirtualNetDeviceChildren)));
ErrorExit:
return Result;
}
int SysFsKernelDebug(PLXT_ARGS Args)
/*++
Description:
This routine tests the debug directory (/sys/kernel/debug).
Arguments:
Args - Supplies the command line arguments.
Return Value:
Returns 0 on success, -1 on failure.
--*/
{
int Result;
LxtCheckResult(LxtCheckDirectoryContents(SYSFS_MNT "/kernel/debug", g_SysFsKernelDebugChildren, LXT_COUNT_OF(g_SysFsKernelDebugChildren)));
LxtCheckResult(LxtCheckDirectoryContents(
SYSFS_MNT "/kernel/debug/tracing", g_SysFsKernelDebugTracingChildren, LXT_COUNT_OF(g_SysFsKernelDebugTracingChildren)));
LxtCheckResult(LxtCheckWrite(SYSFS_MNT "/kernel/debug/tracing/trace_marker", "bogus"));
ErrorExit:
return Result;
}
int SysFsRoot(PLXT_ARGS Args)
/*++
Description:
This routine tests the sysfs root directory (/sys).
Arguments:
Args - Supplies the command line arguments.
Return Value:
Returns 0 on success, -1 on failure.
--*/
{
int Result;
LxtCheckResult(LxtCheckStat(SYSFS_MNT, 1, DT_DIR));
LxtCheckResult(LxtCheckDirectoryContents(SYSFS_MNT, g_SysFsRootChildren, LXT_COUNT_OF(g_SysFsRootChildren)));
ErrorExit:
return Result;
}