Add cpul, date and unitt

This commit is contained in:
Lamdonn 2024-11-15 00:31:10 +08:00
parent ca9bdaad24
commit a2125c2b9f
15 changed files with 1688 additions and 6 deletions

View File

@ -2,6 +2,11 @@
![logo](/image/logo.png)
[![Version](https://img.shields.io/badge/version-0.2.0-blue.svg)](https://gitee.com/Lamdonn/varch)
[![License](https://img.shields.io/badge/license-GPL%202.0-brightgreen.svg)](LICENSE)
[![Author](https://img.shields.io/badge/author-Lamdonn%20%20%20%20%20-brightblue.svg)](Lamdonn@163.com)
![Supported Platforms](https://img.shields.io/badge/platform-Linux%20&%20MinGW-yellow.svg)
## Introduction
[中文版](README.md)
@ -30,6 +35,7 @@ It has the characteristics of **simplicity, universality, and efficiency**, with
| valloc | 01.00.00 | [link](/doc/valloc.md) | [path](./source/01_general) | Dynamic memory usage testing tool
| vlog | 01.01.00 | [link](/doc/vlog.md) | [path](./source/01_general) | Log output module
| intl | 01.00.00 | [link](/doc/intl.md) | [path](./source/01_general) | Large integer arithmetic module
| date | 01.00.00 | [link](/doc/date.md) | [path](./source/01_general) | Date calculation module, calculating date differences, printing calendars, etc
| vctype | 01.00.00 | [link](/doc/vctype.md) | [path](./source/02_vstd) | Similar to the C standard library ctype
| vmath | 01.00.00 | [link](/doc/vmath.md) | [path](./source/02_vstd) | Similar to the C standard library math
| vmem | 01.00.00 | [link](/doc/vmem.md) | [path](./source/02_vstd) | Simple implementation of memory pool
@ -62,6 +68,10 @@ It has the characteristics of **simplicity, universality, and efficiency**, with
| json | 01.00.00 | [link](/doc/json.md) | [path](./source/05_parser) | JSON file parsing generator
| txls | 01.00.00 | [link](/doc/txls.md) | [path](./source/05_parser) | TXLS file parsing generator
| xml | 01.00.00 | [link](/doc/xml.md) | [path](./source/05_parser) | XML file parsing generator
| ramt | 01.00.00 | [link](/doc/ramt.md) | [path](./source/06_performance) | RAM test module
| romt | 01.00.00 | [link](/doc/romt.md) | [path](./source/06_performance) | ROM test module
| cpul | 01.00.00 | [link](/doc/cpul.md) | [path](./source/06_performance) | CPU load test module, including obtaining and increasing load
| unitt | 01.00.00 | [link](/doc/unitt.md) | [path](./source/06_performance) | Simple unit test module
## Usage

View File

@ -2,6 +2,11 @@
![logo](/image/logo.png)
[![Version](https://img.shields.io/badge/version-0.2.0-blue.svg)](https://gitee.com/Lamdonn/varch)
[![License](https://img.shields.io/badge/license-GPL%202.0-brightgreen.svg)](LICENSE)
[![Author](https://img.shields.io/badge/author-Lamdonn%20%20%20%20%20-brightblue.svg)](Lamdonn@163.com)
![Supported Platforms](https://img.shields.io/badge/platform-Linux%20&%20MinGW-yellow.svg)
## 介绍
[English version](README.en.md)
@ -30,6 +35,7 @@ varchwe-architecture意为我们的框架库是嵌入式C语言常用
| valloc | 01.00.00 | [link](/doc/valloc.md) | [path](./source/01_general) | 动态内存使用测试工具
| vlog | 01.01.00 | [link](/doc/vlog.md) | [path](./source/01_general) | 日志输出模块
| intl | 01.00.00 | [link](/doc/intl.md) | [path](./source/01_general) | 大型整数运算模块
| date | 01.00.00 | [link](/doc/date.md) | [path](./source/01_general) | 日期计算模块,计算日期差、打印日历等
| vctype | 01.00.00 | [link](/doc/vctype.md) | [path](./source/02_vstd) | 类似于C标准库ctype
| vmath | 01.00.00 | [link](/doc/vmath.md) | [path](./source/02_vstd) | 类似于C标准库math
| vmem | 01.00.00 | [link](/doc/vmem.md) | [path](./source/02_vstd) | 内存池的简单实现
@ -62,6 +68,10 @@ varchwe-architecture意为我们的框架库是嵌入式C语言常用
| json | 01.00.00 | [link](/doc/json.md) | [path](./source/05_parser) | JSON文件解析生成器
| txls | 01.00.00 | [link](/doc/txls.md) | [path](./source/05_parser) | TXLS文件解析生成器
| xml | 01.00.00 | [link](/doc/xml.md) | [path](./source/05_parser) | XML文件解析生成器
| ramt | 01.00.00 | [link](/doc/ramt.md) | [path](./source/06_performance) | RAM测试模块
| romt | 01.00.00 | [link](/doc/romt.md) | [path](./source/06_performance) | ROM测试模块
| cpul | 01.00.00 | [link](/doc/cpul.md) | [path](./source/06_performance) | CPU负载测试模块包含获取和增加负载
| unitt | 01.00.00 | [link](/doc/unitt.md) | [path](./source/06_performance) | 简易的单元测试模块
## 使用说明

View File

@ -58,6 +58,12 @@ include $(TESTSPACE)/test.mk
TESTSRC += $(APPLICATION_PATH)/main.c
TESTSRC += $(TEST_SRC)
ifeq ($(OS),Windows_NT)
UNAME := Windows
else
UNAME := $(shell uname -s)
endif
##################################################################################
### recipes
##################################################################################
@ -79,7 +85,7 @@ LIBP ?= /usr
# link
${TARP}:$(OBJS)
mkdir -p $(dir $@)
@ mkdir -p $(dir $@)
@ $(CC) $(CFLAG) $(OBJS) -o $(TARP) $(LIBS)
# compile

View File

@ -8,6 +8,7 @@
#include "init.h"
#if defined(_WIN32)
#include <conio.h>
#include <windows.h>
#elif defined(__unix)
#include <termios.h>
#endif
@ -39,9 +40,9 @@ static int kbhit(void)
if (ch != EOF)
{
ungetc(ch, stdin);
return 0;
}
return 1;
}
return 0;
}
#endif
@ -67,8 +68,8 @@ static int into(int argc, char *argv[])
static void console_main(void)
{
int c;
if (!kbhit())
int c = 0;
if (kbhit())
{
c = getchar();
#if CONSOLE_DEBUG == 1
@ -124,6 +125,7 @@ void console_init(void)
if (!console_task) return;
printf("console init! task<%d>!\r\n", console_task);
printf("Press `Enter` to enter the console, input `cmd -h` to get help!\r\n");
/* Export into command */
command_export("into", into);

234
source/01_general/date.c Normal file
View File

@ -0,0 +1,234 @@
/*********************************************************************************************************
* ------------------------------------------------------------------------------------------------------
* file description
* ------------------------------------------------------------------------------------------------------
* \file date.c
* \unit date
* \brief This is a simple date calculate module for C language
* \author Lamdonn
* \version v1.0.0
* \license GPL-2.0
* \copyright Copyright (C) 2023 Lamdonn.
********************************************************************************************************/
#include "date.h"
// TODO: 1582.10.04 - 1582.10.15
/**
* \brief Check if a year is a leap year.
* \param[in] year: The year to check.
* \return 1 if the year is a leap year, 0 otherwise.
*/
uint8_t date_isleap(uint16_t year)
{
return (((year % 4 == 0) && (year % 100 != 0)) || (year % 400 == 0));
}
/**
* \brief Get the number of days in a century.
* \param[in] century: The century to evaluate.
* \return Number of days in the given century.
*/
uint32_t date_century_days(uint16_t century)
{
if (century == 0) return 0u; // No days in century 0
return (century % 4 == 0) ? 36525u : 36524u; // 25 leap years in 400 years
}
/**
* \brief Get the number of days in a year.
* \param[in] year: The year to evaluate.
* \return Number of days in the given year.
*/
uint32_t date_year_days(uint16_t year)
{
if (year == 0) return 0u; // No days in year 0
return date_isleap(year) ? 366u : 365u;
}
/**
* \brief Get the number of days in a month of a given year.
* \param[in] year: The year of the month.
* \param[in] month: The month to evaluate (1-12).
* \return Number of days in the specified month of the specified year.
*/
uint32_t date_month_days(uint16_t year, uint8_t month)
{
if (year == 0) return 0; // No valid month days for year 0
switch (month)
{
case 1: case 3: case 5: case 7: case 8: case 10: case 12:
return 31; // Months with 31 days
case 4: case 6: case 9: case 11:
return 30; // Months with 30 days
case 2:
return date_isleap(year) ? 29 : 28; // February days depending on leap year
default:
return 0; // Invalid month
}
}
/**
* \brief Validate a date.
* \param[in] date: The date structure to validate.
* \return 1 if the date is valid, 0 otherwise.
*/
uint8_t date_isvalid(DATE date)
{
if (date.year == 0 || date.month == 0 || date.day == 0) return 0; // Year, month or day 0 is not valid
return (date_month_days(date.year, date.month) >= date.day);
}
/**
* \brief Calculate the total number of days from a given date to a base date.
* \param[in] date: The date to calculate the total days for.
* \return Total number of days from a base date to the given date, 0 if invalid.
*/
uint32_t date_current_days(DATE date)
{
uint32_t days = 0;
uint16_t year = 1;
uint8_t month = 1;
// Validate the input date; return 0 if invalid
if (!date_isvalid(date)) return 0;
// Count days for complete centuries
for ( ; year + 2000 <= date.year; year += 2000) days += 730485u;
// Count days for complete centuries within the current century
for ( ; year + 100 <= date.year; year += 100) days += date_century_days((year / 100) + 1);
// Count days for complete years within the current century
for ( ; year + 1 <= date.year; year++) days += date_year_days(year);
// Count days for completed months in the current year
for ( ; month < date.month; month++) days += date_month_days(date.year, month);
// Add the days of the current month
days += date.day;
return days;
}
/**
* \brief Get the week number of a given date based on the total days.
* \param[in] date: The date to evaluate.
* \return The week number [1, 7] for the specified date (Mon | Tue | Wed | Thu | Fri | Sat | Sun), 0 if invalid.
*/
uint32_t date_get_week(DATE date)
{
#define bias 0 // Adjust to week start
uint32_t days = date_current_days(date);
uint32_t week = 0;
// If days is 0, return 0 indicating invalid date
if (days == 0) return 0;
week = (days + bias) % 7;
if (week == 0) week = 7;
return week;
}
/**
* \brief Calculate the difference in days between two dates.
* \param[in] date1: The first date.
* \param[in] date2: The second date.
* \return The difference in days between the two dates. Returns 0 if either date is invalid.
*/
int32_t date_diff_days(DATE date1, DATE date2)
{
uint32_t days1 = date_current_days(date1);
uint32_t days2 = date_current_days(date2); // Corrected to use date2
// Return 0 if either date is invalid
if (days1 == 0 || days2 == 0) return 0;
return (int32_t)(days1 - days2);
}
/**
* \brief Convert a number of days to a DATE structure.
* \param[in] days: The number of days to convert.
* \return A DATE structure representing the converted days.
*/
DATE date_from_days(uint32_t days)
{
DATE date = {1, 1, 1}; // Initialize to base date (1/1/1)
uint32_t tdays = 0;
// Return zero date if days are 0
if (days == 0) return DATE(0,0,0);
// Convert days to years
for ( ; days > 730485; days -= 730485) date.year += 2000;
for ( ; days > (tdays = date_century_days((date.year / 100) + 1)); days -= tdays) date.year += 100;
for ( ; days > (tdays = date_year_days(date.year)); days -= tdays) date.year++;
for ( ; days > (tdays = date_month_days(date.year, date.month)); days -= tdays) date.month++;
date.day = days;
return date;
}
/**
* \brief Offset a date by a certain number of days.
* \param[in] date: The date to offset.
* \param[in] days: The number of days to offset (can be negative).
* \return A new DATE structure after applying the offset, or a zero date if invalid.
*/
DATE date_offset(DATE date, int32_t days)
{
if (!date_isvalid(date)) return DATE(0,0,0); // Return zero date if invalid
return date_from_days(date_current_days(date) + days);
}
/**
* \brief Show the calendar for a specific month and year.
* \param[in] year: The year of the calendar to show.
* \param[in] month: The month of the calendar to show.
*/
void date_show(uint16_t year, uint8_t month)
{
DATE date = {year, month, 1};
uint32_t days;
uint32_t tday = 1;
uint32_t week = 0;
int len = 0;
days = date_month_days(year, month);
if (days == 0)
{
printf("[ERROR] Invalid date!\r\n");
return; // Exit if the date is invalid
}
week = date_get_week(date) % 7; // Get the starting day of the week
// Print the calendar header
printf("+-----------------------------------------+\r\n");
len = printf("| %04d/%02d", year, month); while (len++ < 42) printf(" "); printf("|\r\n");
printf("+-----------------------------------------+\r\n");
printf("| Sun | Mon | Tue | Wed | Thu | Fri | Sat |\r\n");
printf("+-----------------------------------------+\r\n");
// Print the days of the month
while (tday <= days)
{
for (int i = 0; i < 7; i++)
{
if (i == 0) printf("|"); // Start of the week
if (i == week && tday <= days)
{
printf(" %3u |", tday); // Print the current day
tday++;
week = (week + 1) % 7; // Move to the next week day
}
else
{
printf(" |"); // Empty space for days not in the current month
}
if (i == 6) printf("\r\n"); // End of the week
}
}
printf("+-----------------------------------------+\r\n"); // End of the calendar
}

120
source/01_general/date.h Normal file
View File

@ -0,0 +1,120 @@
/*********************************************************************************************************
* ------------------------------------------------------------------------------------------------------
* file description
* ------------------------------------------------------------------------------------------------------
* \file date.h
* \unit date
* \brief This is a simple date calculate module for C language
* \author Lamdonn
* \version v1.0.0
* \license GPL-2.0
* \copyright Copyright (C) 2023 Lamdonn.
********************************************************************************************************/
#ifndef __date_H
#define __date_H
#include <stdint.h>
#include <stdio.h>
/* Version infomation */
#define DATE_V_MAJOR 1
#define DATE_V_MINOR 0
#define DATE_V_PATCH 0
typedef struct {
uint16_t year; /**< Year component of the date */
uint8_t month; /**< Month component of the date */
uint8_t day; /**< Day component of the date */
} DATE;
/**
* \brief Macro to create a DATE structure instance.
* \param[in] y: Year component of the date.
* \param[in] m: Month component of the date (1-12).
* \param[in] d: Day component of the date (1-31 depending on the month).
* \return A DATE structure initialized with the specified year, month, and day.
*/
#define DATE(y, m, d) (DATE){.year=(y), .month=(m), .day=(d)}
/**
* \brief Check if a year is a leap year.
* \param[in] year: The year to check.
* \return 1 if the year is a leap year, 0 otherwise.
*/
uint8_t date_isleap(uint16_t year);
/**
* \brief Validate a date.
* \param[in] date: The date structure to validate.
* \return 1 if the date is valid, 0 otherwise.
*/
uint8_t date_isvalid(DATE date);
/**
* \brief Get the number of days in a century.
* \param[in] century: The century to evaluate.
* \return Number of days in the given century.
*/
uint32_t date_century_days(uint16_t century);
/**
* \brief Get the number of days in a year.
* \param[in] year: The year to evaluate.
* \return Number of days in the given year.
*/
uint32_t date_year_days(uint16_t year);
/**
* \brief Get the number of days in a month of a given year.
* \param[in] year: The year of the month.
* \param[in] month: The month to evaluate (1-12).
* \return Number of days in the specified month of the specified year.
*/
uint32_t date_month_days(uint16_t year, uint8_t month);
/**
* \brief Get the week number of a given date based on the total days.
* \param[in] date: The date to evaluate.
* \return The week number [1, 7] for the specified date (Mon | Tue | Wed | Thu | Fri | Sat | Sun), 0 if invalid.
*/
uint32_t date_get_week(DATE date);
/**
* \brief Calculate the total number of days from a given date to a base date.
* \param[in] date: The date to calculate the total days for.
* \return Total number of days from a base date to the given date, 0 if invalid.
*/
uint32_t date_current_days(DATE date);
/**
* \brief Calculate the difference in days between two dates.
* \param[in] date1: The first date.
* \param[in] date2: The second date.
* \return The difference in days between the two dates. Returns 0 if either date is invalid.
*/
int32_t date_diff_days(DATE date1, DATE date2);
/**
* \brief Convert a number of days to a DATE structure.
* \param[in] days: The number of days to convert.
* \return A DATE structure representing the converted days.
*/
DATE date_from_days(uint32_t days);
/**
* \brief Offset a date by a certain number of days.
* \param[in] date: The date to offset.
* \param[in] days: The number of days to offset (can be negative).
* \return A new DATE structure after applying the offset, or a zero date if invalid.
*/
DATE date_offset(DATE date, int32_t days);
/**
* \brief Show the calendar for a specific month and year.
* \param[in] year: The year of the calendar to show.
* \param[in] month: The month of the calendar to show.
*/
void date_show(uint16_t year, uint8_t month);
#endif

View File

@ -0,0 +1,211 @@
/*********************************************************************************************************
* ------------------------------------------------------------------------------------------------------
* file description
* ------------------------------------------------------------------------------------------------------
* \file cpul.c
* \unit cpul
* \brief This is a simple cpuload module for C language
* \author Lamdonn
* \version v1.0.0
* \license GPL-2.0
* \copyright Copyright (C) 2023 Lamdonn.
********************************************************************************************************/
#include "cpul.h"
#include <stdlib.h>
#include <string.h>
// Buffer for CRC calculation, initialized with some values
uint8_t calbuffer[CPUL_GEN_BSIZE] = {'A', 'B', 0};
/**
* \brief Adjust the refined load based on current and target loads.
*
* This function controls the refined load adjustment by comparing
* the current load with the target load and modifying the refined
* load accordingly.
*
* \param[in] cpul: Pointer to the CPUL instance.
* \return Returns the adjusted refined load value.
*/
static uint32_t controller(CPUL *cpul)
{
// If the current load is less than the target load
if (cpul->ctrl.cload < cpul->ctrl.tload)
{
// If adding resolution to refined load does not exceed its current value
if (cpul->ctrl.refine + cpul->resolution > cpul->ctrl.refine)
{
// Increase the refined load by the resolution value
cpul->ctrl.refine += cpul->resolution;
}
}
// If the current load is greater than target load + 1
else if (cpul->ctrl.cload > (cpul->ctrl.tload + 1))
{
// If the refined load is greater than or equal to the resolution
if (cpul->ctrl.refine >= cpul->resolution)
{
// Decrease the refined load by the resolution value
cpul->ctrl.refine -= cpul->resolution;
}
}
return cpul->ctrl.refine; // Return the adjusted refined load
}
/**
* \brief Calculate CRC8 checksum.
*
* This function computes the CRC8 checksum for a given data buffer.
* It iterates through each byte of data and processes it to generate
* the CRC value.
*
* \param[in] data: Pointer to the data buffer.
* \param[in] len: Length of the data buffer.
* \return Returns the calculated CRC8 value.
*/
static uint8_t crc8(uint8_t *data, uint32_t len)
{
uint8_t i; // Loop index for bit processing
uint8_t crc = 0; // Initialize CRC value to 0
while (len--) // Process each byte in the data buffer
{
crc ^= *data++; // XOR the current byte with the CRC value
for (i = 0; i < 8; i++) // Process each bit of the byte
{
if (crc & 0x80) // If the highest bit of CRC is set
crc = (crc << 1) ^ 0x07; // Shift left and XOR with the polynomial
else
crc <<= 1; // Just shift left if the highest bit is not set
}
}
return crc; // Return the calculated CRC8 value
}
/**
* \brief Update the granularity of the load control.
*
* This function updates the calbuffer values based on the refined load
* using CRC8 checksum for each iteration specified by the input parameter.
*
* \param[in] input: Number of iterations to update the buffer.
* \return none.
*/
static void granularity(uint32_t input)
{
// Loop through the specified number of iterations
for (uint32_t i = 0; i < input; i++)
{
// Update calbuffer with a CRC8 value calculated from the current buffer
calbuffer[calbuffer[0] % sizeof(calbuffer)] = crc8(calbuffer, sizeof(calbuffer));
}
}
/**
* \brief Initialize the CPUL instance.
*
* This function initializes the CPUL structure to default values
* and checks for valid pointers.
*
* \param[in] cpul: Pointer to the CPUL instance.
* \return Returns CPUL_E_OK on success, otherwise an error code.
*/
int cpul_init(CPUL *cpul)
{
// Check if the cpul pointer is valid
if (!cpul) return CPUL_E_INVALID;
// Check if the raw function pointer is valid
if (!cpul->raw) return CPUL_E_RAW;
cpul->ctrl.cload = 0xFFFF; // Set current load to untested value
cpul->ctrl.tload = 0; // Default target load to zero (no load increase)
cpul->ctrl.refine = 0; // Initialize refined load
return CPUL_E_OK; // Initialization successful
}
/**
* \brief Get the current CPU load.
*
* This function retrieves the current load from the CPUL instance
* and checks for validity of parameters and state.
*
* \param[in] cpul: Pointer to the CPUL instance.
* \param[out] load: Pointer to store the current load value.
* \return Returns CPUL_E_OK on success, otherwise an error code.
*/
int cpul_get(CPUL *cpul, uint16_t *load)
{
// Check if the cpul pointer is valid
if (!cpul) return CPUL_E_INVALID;
// Check if the raw function pointer is valid
if (!cpul->raw) return CPUL_E_RAW;
// Check if the load parameter is valid
if (!load) return CPUL_E_PARA;
// If current load is still untested, return an error
if (cpul->ctrl.cload == 0xFFFF) return CPUL_E_NTEST;
// Check if the current load exceeds the maximum allowed value
if (cpul->ctrl.cload > 10000) return CPUL_E_OVER;
*load = cpul->ctrl.cload; // Retrieve the current load value
return CPUL_E_OK; // Success
}
/**
* \brief Set the target CPU load.
*
* This function sets the target load for the CPUL instance and checks for valid parameters.
*
* \param[in] cpul: Pointer to the CPUL instance.
* \param[in] load: Target load value to set.
* \return Returns CPUL_E_OK on success, otherwise an error code.
*/
int cpul_set(CPUL *cpul, uint16_t load)
{
// Check if the cpul pointer is valid
if (!cpul) return CPUL_E_INVALID;
// Check if the raw function pointer is valid
if (!cpul->raw) return CPUL_E_RAW;
// Check if the load parameter is zero
if (!load) return CPUL_E_PARA;
// Check if the load exceeds the maximum allowed value
if (load > 10000) return CPUL_E_OVER;
cpul->ctrl.tload = load; // Set the target load
return CPUL_E_OK; // Success
}
/**
* \brief Execute a CPUL management task.
*
* This function executes a task to manage the CPU load based on
* the current and target load values.
*
* \param[in] cpul: Pointer to the CPUL instance.
* \return Returns CPUL_E_OK on success, otherwise an error code.
*/
int cpul_task(CPUL *cpul)
{
// Check if the cpul pointer is valid
if (!cpul) return CPUL_E_INVALID;
// Check if the raw function pointer is valid
if (!cpul->raw) return CPUL_E_RAW;
// Call the raw function to get the current load value
cpul->ctrl.cload = cpul->raw(cpul->coreid);
// If the target load is not zero, perform load management
if (cpul->ctrl.tload != 0)
{
// Adjust the refined load based on current and target load
cpul->ctrl.refine = controller(cpul);
// Update granularity based on the refined load
granularity(cpul->ctrl.refine);
}
return CPUL_E_OK; // Success
}

View File

@ -0,0 +1,100 @@
/*********************************************************************************************************
* ------------------------------------------------------------------------------------------------------
* file description
* ------------------------------------------------------------------------------------------------------
* \file cpul.h
* \unit cpul
* \brief This is a simple cpuload module for C language
* \author Lamdonn
* \version v1.0.0
* \license GPL-2.0
* \copyright Copyright (C) 2023 Lamdonn.
********************************************************************************************************/
#ifndef __cpul_H
#define __cpul_H
#include "stdint.h"
/* Version infomation */
#define CPUL_V_MAJOR 0
#define CPUL_V_MINOR 1
#define CPUL_V_PATcH 0
#define CPUL_GEN_BSIZE 4
#define CPUL_E_OK 0 // Success
#define CPUL_E_INVALID 1 // Invalid `CPUL` pointer
#define CPUL_E_RAW 2 // Invalid raw function
#define CPUL_E_PARA 3 // Invalid parameter
#define CPUL_E_NTEST 4 // CPUL load testing has not started
#define CPUL_E_OVER 5 // CPUL load exceeds range
typedef uint16_t (*cpul_raw_t)(uint8_t coreid); // Type definition for the raw CPUL load function
/**
* \brief Structure to control CPUL load parameters.
*/
typedef struct
{
uint32_t refine; ///< Refined load value
uint16_t cload; ///< Current load value
uint16_t tload; ///< Target load value
} CPUL_CTRL;
/**
* \brief Structure to represent a CPU Load Manager.
*/
typedef struct
{
uint8_t coreid; ///< Core ID
cpul_raw_t raw; ///< Pointer to the raw CPUL load function
uint32_t resolution; ///< Resolution of the load control
CPUL_CTRL ctrl; ///< Control structure for CPUL management
} CPUL;
/**
* \brief Initialize the CPUL instance.
*
* This function initializes the CPUL structure to default values
* and checks for valid pointers.
*
* \param[in] cpul: Pointer to the CPUL instance.
* \return Returns CPUL_E_OK on success, otherwise an error code.
*/
int cpul_init(CPUL *cpul);
/**
* \brief Get the current CPU load.
*
* This function retrieves the current load from the CPUL instance
* and checks for validity of parameters and state.
*
* \param[in] cpul: Pointer to the CPUL instance.
* \param[out] load: Pointer to store the current load value.
* \return Returns CPUL_E_OK on success, otherwise an error code.
*/
int cpul_get(CPUL *cpul, uint16_t *load);
/**
* \brief Set the target CPU load.
*
* This function sets the target load for the CPUL instance and checks for valid parameters.
*
* \param[in] cpul: Pointer to the CPUL instance.
* \param[in] load: Target load value to set.
* \return Returns CPUL_E_OK on success, otherwise an error code.
*/
int cpul_set(CPUL *cpul, uint16_t load);
/**
* \brief Execute a CPUL management task.
*
* This function executes a task to manage the CPU load based on
* the current and target load values.
*
* \param[in] cpul: Pointer to the CPUL instance.
* \return Returns CPUL_E_OK on success, otherwise an error code.
*/
int cpul_task(CPUL *cpul);
#endif

View File

@ -0,0 +1,306 @@
/*********************************************************************************************************
* ------------------------------------------------------------------------------------------------------
* file description
* ------------------------------------------------------------------------------------------------------
* \file unitt.c
* \unit unitt
* \brief This is a simple unit test module for C language
* \author Lamdonn
* \version v1.0.0
* \license GPL-2.0
* \copyright Copyright (C) 2023 Lamdonn.
********************************************************************************************************/
#include "unitt.h"
/**
* \brief Assert that a condition is true.
*
* This function checks if the given condition is true. If it is false,
* it outputs an assertion failure message and returns a failure code.
*
* \param[in] condition: The condition to evaluate.
* \param[in] message: The message to display if the assertion fails.
* \return Returns UNITT_E_OK if the assertion passes, otherwise UNITT_E_FAIL.
*/
int unitt_det_true(int condition, const char* message)
{
if (!condition)
{
fprintf(stderr, "Assertion Failed: %s\n", message);
return UNITT_E_FAIL;
}
return UNITT_E_OK;
}
/**
* \brief Assert that a condition is false.
*
* This function checks if the given condition is false. If it is true,
* it outputs an assertion failure message and returns a failure code.
*
* \param[in] condition: The condition to evaluate.
* \param[in] message: The message to display if the assertion fails.
* \return Returns UNITT_E_OK if the assertion passes, otherwise UNITT_E_FAIL.
*/
int unitt_det_false(int condition, const char* message)
{
if (condition)
{
fprintf(stderr, "Assertion Failed: %s\n", message);
return UNITT_E_FAIL;
}
return UNITT_E_OK;
}
/**
* \brief Assert that two integers are equal.
*
* This function checks whether the expected and actual values are equal.
* If they are not equal, it outputs an assertion failure message with
* both values and returns a failure code.
*
* \param[in] expected: The expected value.
* \param[in] actual: The actual value.
* \param[in] message: The message to display if the assertion fails.
* \return Returns UNITT_E_OK if the assertion passes, otherwise UNITT_E_FAIL.
*/
int unitt_det_equal(int expected, int actual, const char* message)
{
if (expected != actual)
{
fprintf(stderr, "Assertion Failed: %s (Expected: %d, Actual: %d)\n", message, expected, actual);
return UNITT_E_FAIL;
}
return UNITT_E_OK;
}
/**
* \brief Assert that two integers are not equal.
*
* This function checks whether the expected and actual values are not equal.
* If they are equal, it outputs an assertion failure message and returns a failure code.
*
* \param[in] expected: The expected value.
* \param[in] actual: The actual value.
* \param[in] message: The message to display if the assertion fails.
* \return Returns UNITT_E_OK if the assertion passes, otherwise UNITT_E_FAIL.
*/
int unitt_det_nequal(int expected, int actual, const char* message)
{
if (expected == actual)
{
fprintf(stderr, "Assertion Failed: %s (Expected not equal to Actual)\n", message);
return UNITT_E_FAIL;
}
return UNITT_E_OK;
}
/**
* \brief Assert that a pointer is NULL.
*
* This function checks whether the given pointer is NULL. If it is not NULL,
* it outputs an assertion failure message with the pointer's value and returns a failure code.
*
* \param[in] pointer: The pointer to evaluate.
* \param[in] message: The message to display if the assertion fails.
* \return Returns UNITT_E_OK if the assertion passes, otherwise UNITT_E_FAIL.
*/
int unitt_det_null(void* pointer, const char* message)
{
if (pointer != NULL)
{
fprintf(stderr, "Assertion Failed: %s (Expected NULL, Actual: %p)\n", message, pointer);
return UNITT_E_FAIL;
}
return UNITT_E_OK;
}
/**
* \brief Assert that a pointer is not NULL.
*
* This function checks whether the given pointer is not NULL. If it is NULL,
* it outputs an assertion failure message and returns a failure code.
*
* \param[in] pointer: The pointer to evaluate.
* \param[in] message: The message to display if the assertion fails.
* \return Returns UNITT_E_OK if the assertion passes, otherwise UNITT_E_FAIL.
*/
int unitt_det_nnull(void* pointer, const char* message)
{
if (pointer == NULL)
{
fprintf(stderr, "Assertion Failed: %s (Expected non-NULL, Actual: NULL)\n", message);
return UNITT_E_FAIL;
}
return UNITT_E_OK;
}
/**
* \brief Assert that two floats are approximately equal.
*
* This function checks whether the expected and actual float values are approximately equal
* within a given epsilon range. If they are not, it outputs an assertion failure message
* with both values and returns a failure code.
*
* \param[in] expected: The expected float value.
* \param[in] actual: The actual float value.
* \param[in] epsilon: The acceptable difference between the two values.
* \param[in] message: The message to display if the assertion fails.
* \return Returns UNITT_E_OK if the assertion passes, otherwise UNITT_E_FAIL.
*/
int unitt_det_float(float expected, float actual, float epsilon, const char* message)
{
if (fabs(expected - actual) > epsilon)
{
fprintf(stderr, "Assertion Failed: %s (Expected: %.6f, Actual: %.6f)\n", message, expected, actual);
return UNITT_E_FAIL;
}
return UNITT_E_OK;
}
/**
* \brief Assert that two strings are equal.
*
* This function checks whether the expected and actual strings are equal.
* If they are not equal, it outputs an assertion failure message with both strings
* and returns a failure code.
*
* \param[in] expected: The expected string.
* \param[in] actual: The actual string.
* \param[in] message: The message to display if the assertion fails.
* \return Returns UNITT_E_OK if the assertion passes, otherwise UNITT_E_FAIL.
*/
int unitt_det_string(const char* expected, const char* actual, const char* message)
{
if (strcmp(expected, actual) != 0)
{
fprintf(stderr, "Assertion Failed: %s (Expected: '%s', Actual: '%s')\n", message, expected, actual);
return UNITT_E_FAIL;
}
return UNITT_E_OK;
}
/**
* \brief Handle a test failure.
*
* This function is called when a test fails. It outputs the name of the failed test.
*
* \param[in] name: The name of the failed test.
* \return Returns UNITT_E_OK.
*/
int unitt_fail_handle(const char* name)
{
printf("Failure in test: %s\n", name);
return UNITT_E_OK;
}
/**
* \brief Execute a test suite.
*
* This function runs all the test cases within the provided test suites.
* It measures the execution time for each test and outputs a summary report.
*
* \param[in] suites: Array of test suites to execute.
* \param[in] count: Number of test suites in the array.
* \param[in] failcb: Callback function to handle test failures.
* \param[in] specific: Specific test name to execute (NULL for all).
* \param[in] filename: Output filename for results (NULL for stdout).
* \return none.
*/
void unitt_execute(UNITT* suites, uint32_t count, unitt_failcb_t failcb, const char* specific, const char* filename)
{
UNITT* suite = NULL;
UNITT_TCASE* tcase = NULL;
uint64_t cstart = 0, cend = 0; // Record the start and end time of the test
FILE* output = stdout; // Default output to standard output
if (filename != NULL)
{
output = fopen(filename, "w");
if (output == NULL)
{
perror("Failed to open output file");
return;
}
}
// Iterate over each test suite
for (int i = 0; i < count; i++)
{
suite = &suites[i];
fprintf(output, "Running test suite: %s\n", suite->name);
// Iterate over each test case
for (int j = 0; j < suite->count; j++)
{
tcase = &suite->tests[j];
if (specific && strcmp(tcase->name, specific) != 0)
{
continue; // Skip non-matching tests
}
// Execute setup function before the test
if (tcase->setup) tcase->setup();
// Record start time
if (suite->clock) cstart = suite->clock();
// Execute test function
if (UNITT_E_OK == tcase->func())
{
tcase->passed++;
}
else
{
if (failcb) failcb(tcase->name);
}
// Record end time
if (suite->clock) cend = suite->clock();
// Accumulate the time taken for the test
if (suite->clock) tcase->time += (cend - cstart);
// Execute teardown function after the test
if (tcase->teardown) tcase->teardown();
tcase->tested++;
}
}
// Output summary of the tests
for (int i = 0; i < count; i++)
{
suite = &suites[i];
fprintf(output, "Test suite `%s` report: \r\n", suite->name);
// Iterate over each test case
for (int j = 0; j < suite->count; j++)
{
tcase = &suite->tests[j];
fprintf(output, "[%s] Summary: tested %u, passed %u, time %llu us.\r\n",
tcase->name,
tcase->tested,
tcase->passed,
tcase->time
);
}
}
if (filename != NULL)
{
fclose(output);
}
}

View File

@ -0,0 +1,184 @@
/*********************************************************************************************************
* ------------------------------------------------------------------------------------------------------
* file description
* ------------------------------------------------------------------------------------------------------
* \file unitt.h
* \unit unitt
* \brief This is a simple unit test module for C language
* \author Lamdonn
* \version v1.0.0
* \license GPL-2.0
* \copyright Copyright (C) 2023 Lamdonn.
********************************************************************************************************/
#ifndef __unitt_H
#define __unitt_H
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <stdint.h>
/* Version infomation */
#define UNITT_V_MAJOR 0
#define UNITT_V_MINOR 1
#define UNITT_V_PATcH 0
// Type definition for a clock function
typedef uint64_t (*unitt_clock_t)();
// Type definition for a test function
typedef int (*unitt_func_t)();
// Type definition for a setup function before the test
typedef int (*unitt_setup_t)();
// Type definition for a teardown function after the test
typedef int (*unitt_teardown_t)();
// Type definition for a failure callback function
typedef int (*unitt_failcb_t)(const char* name);
// Type definition for a random input generation function
typedef int (*unitt_randin_t)();
/**
* \brief Structure representing a test case
*/
typedef struct
{
const char* name; ///< Name of the test
unitt_func_t func; ///< Pointer to the test function
unitt_setup_t setup; ///< Pointer to the setup function
unitt_teardown_t teardown; ///< Pointer to the teardown function
unitt_randin_t random_input; ///< Pointer to the random input generation function
uint32_t tested; ///< Count of tests executed
uint32_t passed; ///< Count of tests passed
uint64_t time; ///< Total time taken for the test
} UNITT_TCASE;
/**
* \brief Structure representing a test suite
*/
typedef struct
{
const char* name; ///< Name of the test suite
UNITT_TCASE* tests; ///< Array of test cases
uint32_t count; ///< Number of test cases
unitt_clock_t clock; ///< Pointer to the clock function for measuring time
} UNITT;
#define UNITT_E_OK (0) // Success return code
#define UNITT_E_FAIL (-1) // Failure return code
/**
* \brief Assert that a condition is true
* \param[in] condition: The condition to evaluate
* \param[in] message: The message to display if the assertion fails
* \return Returns UNITT_E_OK if the assertion passes, otherwise UNITT_E_FAIL
*/
int unitt_det_true(int condition, const char* message);
/**
* \brief Assert that a condition is false
* \param[in] condition: The condition to evaluate
* \param[in] message: The message to display if the assertion fails
* \return Returns UNITT_E_OK if the assertion passes, otherwise UNITT_E_FAIL
*/
int unitt_det_false(int condition, const char* message);
/**
* \brief Assert that two integers are equal
* \param[in] expected: The expected value
* \param[in] actual: The actual value
* \param[in] message: The message to display if the assertion fails
* \return Returns UNITT_E_OK if the assertion passes, otherwise UNITT_E_FAIL
*/
int unitt_det_equal(int expected, int actual, const char* message);
/**
* \brief Assert that two integers are not equal
* \param[in] expected: The expected value
* \param[in] actual: The actual value
* \param[in] message: The message to display if the assertion fails
* \return Returns UNITT_E_OK if the assertion passes, otherwise UNITT_E_FAIL
*/
int unitt_det_nequal(int expected, int actual, const char* message);
/**
* \brief Assert that a pointer is NULL
* \param[in] pointer: The pointer to evaluate
* \param[in] message: The message to display if the assertion fails
* \return Returns UNITT_E_OK if the assertion passes, otherwise UNITT_E_FAIL
*/
int unitt_det_null(void* pointer, const char* message);
/**
* \brief Assert that a pointer is not NULL
* \param[in] pointer: The pointer to evaluate
* \param[in] message: The message to display if the assertion fails
* \return Returns UNITT_E_OK if the assertion passes, otherwise UNITT_E_FAIL
*/
int unitt_det_nnull(void* pointer, const char* message);
/**
* \brief Assert that two floats are approximately equal
* \param[in] expected: The expected float value
* \param[in] actual: The actual float value
* \param[in] epsilon: The acceptable difference between the two values
* \param[in] message: The message to display if the assertion fails
* \return Returns UNITT_E_OK if the assertion passes, otherwise UNITT_E_FAIL
*/
int unitt_det_float(float expected, float actual, float epsilon, const char* message);
/**
* \brief Assert that two strings are equal
* \param[in] expected: The expected string
* \param[in] actual: The actual string
* \param[in] message: The message to display if the assertion fails
* \return Returns UNITT_E_OK if the assertion passes, otherwise UNITT_E_FAIL
*/
int unitt_det_string(const char* expected, const char* actual, const char* message);
/**
* \brief Handle a test failure
* \param[in] name: The name of the failed test
* \return Returns UNITT_E_OK
*/
int unitt_fail_handle(const char* name);
/**
* \brief Execute a test suite
* \param[in] suites: Array of test suites to execute
* \param[in] count: Number of test suites in the array
* \param[in] failcb: Callback function to handle test failures
* \param[in] specific: Specific test name to execute (NULL for all)
* \param[in] filename: Output filename for results (NULL for stdout)
* \return none
*/
void unitt_execute(UNITT* suites, uint32_t count, unitt_failcb_t failcb, const char* specific, const char* filename);
/**
* \brief Macro to define a test case
* \param name: Name of the test case
*/
#define UNITT_TCASE(name) { #name, name, NULL, NULL, NULL, 0, 0, 0 }
/**
* \brief Macro to execute a set of test cases
* \param suites: Array of test cases to execute
*/
#define UNITT_EXE(suites) unitt_execute((suites), sizeof(suites) / sizeof(suites[0]), unitt_fail_handle, 0, 0)
/**
* \brief Macro to execute a set of test cases with additional parameters
* \param suites: Array of test cases to execute
* \param count: Number of test cases
* \param mode: Execution mode
* \param specific: Specific test name to execute
* \param output: Output filename for results
*/
#define UNITT_EXE2(suites, count, mode, specific, output) unitt_execute(suites, count, unitt_fail_handle, specific, output)
#endif // __unit_H

View File

@ -45,6 +45,11 @@ TEST_INC =
# TEST_SRC += $(TESTSPACE)/test_sList.c
# TEST_SRC += $(TESTSPACE)/test_dList.c
# TEST_SRC += $(TESTSPACE)/test_cQueue.c
TEST_SRC += $(TESTSPACE)/test_intl.c
# TEST_SRC += $(TESTSPACE)/test_intl.c
# TEST_SRC += $(TESTSPACE)/test_ramt.c
# TEST_SRC += $(TESTSPACE)/test_cpul.c
# TEST_SRC += $(TESTSPACE)/test_date.c
TEST_SRC += $(TESTSPACE)/test_unitt.c
export TEST_SRC TEST_INC

200
test/test_cpul.c Normal file
View File

@ -0,0 +1,200 @@
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <math.h>
#include <pthread.h>
#include <time.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sched.h>
#include "init.h"
#include "cpul.h"
#define CORE_NUM_MAX 32
#define LINE_BUFFER_SIZE 1024
/**
* Structure for recording CPU counters in stat
*/
typedef struct {
uint64_t user; /**< Time spent in user mode */
uint64_t nice; /**< Time spent in low-priority user mode */
uint64_t system; /**< Time spent in system mode */
uint64_t idle; /**< Time spent waiting for tasks */
uint64_t iowait; /**< Time spent waiting for I/O to complete */
uint64_t irq; /**< Time spent processing interrupts */
uint64_t softirq; /**< Time spent processing soft interrupts */
uint64_t steal; /**< Time spent by other OS in virtual environment */
uint64_t guest; /**< Time spent running guest OS */
uint64_t guest_nice; /**< Time spent running low priority guest OS */
} cputime_t;
static uint16_t loadTable[CORE_NUM_MAX] = {0};
static cputime_t read_stat(int coreid)
{
cputime_t work;
FILE *file;
char line[LINE_BUFFER_SIZE];
file = fopen("/proc/stat", "rb");
if (file == NULL) {
}
if (fgets(line, sizeof(line), file) == NULL) {
goto error;
}
if (sscanf(line, "cpu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu",
&work.user,
&work.nice,
&work.system,
&work.idle,
&work.iowait,
&work.irq,
&work.softirq,
&work.steal,
&work.guest,
&work.guest_nice) < 4) {
goto error;
}
if (coreid > 0)
{
int i;
for (i = 0; i < coreid; i++)
{
if (fgets(line, sizeof(line), file) == NULL)
{
goto error;
}
if (sscanf(line, "cpu%*u %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu",
&work.user,
&work.nice,
&work.system,
&work.idle,
&work.iowait,
&work.irq,
&work.softirq,
&work.steal,
&work.guest,
&work.guest_nice) < 4)
{
goto error;
}
}
}
error:
fclose(file);
return work;
}
void *loadupdate_entry(void *ptr)
{
const int coreNum = *(int *)ptr;
cputime_t before[coreNum], after[coreNum], diff[coreNum];
int i = 0;
while(1)
{
/* Calcul real time load */
for (i = 0; i < coreNum; i++) before[i] = read_stat(i);
usleep(1000000);
for (i = 0; i < coreNum; i++) after[i] = read_stat(i);
for (i = 0; i < coreNum; i++)
{
if (after[i].user > before[i].user && after[i].idle > before[i].idle)
{
diff[i].user = after[i].user - before[i].user;
diff[i].idle = after[i].idle - before[i].idle;
loadTable[i] = (uint16_t)(((float)(diff[i].user) / (float)(diff[i].user + diff[i].idle)) * 10000);
}
else
{
loadTable[i] = 0;
}
// printf("[core%d] load %d\r\n", i, loadTable[i]);
}
}
}
uint16_t cpul_raw(uint8_t coreid)
{
if (coreid >= CORE_NUM_MAX) return 0xFFFF;
return (uint16_t)(loadTable[coreid]);
}
void *loadgen_entry(void *ptr)
{
#define PERIOD 10
const int coreid = *(int *)ptr;
CPUL cpul;
int ret = 0;
uint32_t count = 0;
uint16_t load = 0;
cpul.coreid = coreid;
cpul.resolution = 10;
cpul.raw = cpul_raw;
ret = cpul_init(&cpul);
ret = cpul_set(&cpul, 5000);
while(1)
{
count += PERIOD;
if (count >= 25200000) count = 0;
if (count % 1000 == 0)
{
ret = cpul_get(&cpul, &load);
printf("cpul_get<%d> %2d.%02d%%, %d, %d\r\n", coreid, (uint16_t)(load / 100), load % 100, cpul.ctrl.tload, cpul.ctrl.refine);
}
cpul_task(&cpul);
usleep(1000 * PERIOD);
}
}
static void test(void)
{
int num_cpus = sysconf(_SC_NPROCESSORS_CONF);
pthread_t thread_update, thread_gen[num_cpus];
int coreid[num_cpus];
int ret;
printf("Number of CPUs: %d\n", num_cpus);
ret = pthread_create(&thread_update, NULL, &loadupdate_entry, &num_cpus);
if (ret != 0) {
printf("pthread_create failed!\n");
}
for (int i = 0; i < num_cpus; i++)
{
coreid[i] = i;
ret = pthread_create(&thread_gen[i], NULL, &loadgen_entry, &coreid[i]);
if (ret != 0) {
printf("pthread_create failed!\n");
}
cpu_set_t cpuset;
CPU_ZERO(&cpuset);
CPU_SET(i, &cpuset);
sched_setaffinity(thread_gen[i], sizeof(cpu_set_t), &cpuset);
}
pthread_join(thread_update, NULL);
for (int i = 0; i < num_cpus; i++)
{
pthread_join(thread_gen[i], NULL);
}
}
init_export_app(test);

69
test/test_date.c Normal file
View File

@ -0,0 +1,69 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "init.h"
#include "date.h"
#if 0
static int century_days(int century)
{
int days = 0;
int year = (century - 1) * 100 + 1;
for (int i = 0; i < 100; i++)
{
days += date_year_days(year + i);
}
return days;
}
static int thousand2_days(int base)
{
int days = 0;
for (int i = 0; i < 2000; i++)
{
days += date_year_days(base + i);
}
return days;
}
static int thousand3_days(int base)
{
int days = 0;
int century = (base / 100) + 1;
for (int i = 0; i < 20; i++)
{
// days += century_days(century + i);
days += date_century_days(century + i);
}
return days;
}
#endif
static void test(void)
{
printf("month days %d\r\n", date_month_days(2024, 11));
printf("date_isleap %d\r\n", date_isleap(1582));
// printf("date_current_days %d\r\n", date_current_days(DATE(1,1,1)));
// printf("date_current_days %d\r\n", date_current_days(DATE(2000,12,31)));
// printf("date_current_days %d\r\n", date_current_days(DATE(2001,1,1)));
// printf("date_current_days %d\r\n", date_current_days(DATE(2024,11,9)));
printf("date_get_week %d\r\n", date_get_week(DATE(2024,11,11)));
printf("date_diff_days %d\r\n", date_diff_days(DATE(2018,3,14), DATE(2024,11,10)));
// DATE date = date_from_days(date_current_days(DATE(2024,11,30)));
DATE date = date_offset(DATE(2024,11,30), -1);
printf("%d.%d.%d\r\n", date.year,date.month,date.day);
date_show(1998,7);
date_show(2024,11);
date_show(2224,11);
}
init_export_app(test);

43
test/test_ramt.c Normal file
View File

@ -0,0 +1,43 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "init.h"
#include "tool.h"
#include "ramt.h"
#include "kern.h"
#define TASK_PERIOD 5 // ms
static uint8_t buffer[128];
static RAMT ramt_object;
static void test_task(void)
{
static int count = 0;
count += TASK_PERIOD;
ramt_task(&ramt_object);
if (count % 1000 == 0)
{
printf("result %08X\r\n", ramt_result(&ramt_object));
}
}
static void test_ramt(void)
{
task_t task;
printf("ramt test!\r\n");
ramt_object.base = (void *)buffer;
ramt_object.size = sizeof(buffer);
ramt_init(&ramt_object);
ramt_start(&ramt_object, RAMT_MODE_NORMAL, 0xFFFFFFFF);
task = task_create(TASK_PERIOD, test_task);
printf("task <%d>\r\n", task);
}
init_export_app(test_ramt);

182
test/test_unitt.c Normal file
View File

@ -0,0 +1,182 @@
#include <stdio.h>
#include <string.h>
#include <sys/time.h>
#include "init.h"
#include "unitt.h"
#include "kern.h"
#if 0
#ifdef _WIN32
#include <windows.h>
#include <psapi.h> // -lPsapi
#else
#include <unistd.h>
#include <pthread.h>
#endif
void get_memory_usage(int* resident_set_size, int* virtual_memory_size)
{
#ifdef _WIN32
PROCESS_MEMORY_COUNTERS pmc;
if (GetProcessMemoryInfo(GetCurrentProcess(), &pmc, sizeof(pmc))) {
*resident_set_size = pmc.WorkingSetSize / 1024; // 转换为KB
*virtual_memory_size = pmc.PagefileUsage / 1024; // 转换为KB
} else {
*resident_set_size = 0;
*virtual_memory_size = 0;
}
#else
FILE* file = fopen("/proc/self/statm", "r");
if (file) {
fscanf(file, "%d %d", resident_set_size, virtual_memory_size);
fclose(file);
} else {
*resident_set_size = 0;
*virtual_memory_size = 0;
}
#endif
}
#endif
#define SINGLE_TCOUNT 1000
uint64_t unitt_clock(void)
{
struct timeval mstime;
uint64_t us = 0;
gettimeofday(&mstime, NULL);
us = mstime.tv_sec * 1000000 + mstime.tv_usec;
return us;
}
// 计算两个整数的和
int unit_add(int a, int b)
{
return a + b;
}
// 计算两个整数的差
int unit_subtract(int a, int b)
{
return a - b;
}
// 计算两个整数的乘积
int unit_multiply(int a, int b)
{
return a * b;
}
// 计算两个整数的商
float unit_divide(int a, int b)
{
if (b == 0)
{
return 0; // 简单处理,真实应用中应更严格处理
}
return (float)a / (float)b;
}
// 测试前的初始化函数
int setup()
{
// 初始化代码(如果需要)
return 0;
}
// 测试后的清理函数
int teardown()
{
// 清理代码(如果需要)
return 0;
}
// 随机输入生成函数
int random_input()
{
return rand() % 100; // 生成0到99之间的随机整数
}
// 测试加法函数,使用随机输入
int test_add()
{
// 进行10次随机测试
for (int i = 0; i < SINGLE_TCOUNT; i++)
{
int a = random_input();
int b = random_input();
if (UNITT_E_FAIL == unitt_det_equal(unit_add(a, b), a + b, "Random addition failed")) return UNITT_E_FAIL;
}
return UNITT_E_OK;
}
// 测试减法函数,使用随机输入
int test_subtract()
{
// 进行10次随机测试
for (int i = 0; i < SINGLE_TCOUNT; i++)
{
int a = random_input();
int b = random_input();
if (UNITT_E_FAIL == unitt_det_equal(unit_subtract(a, b), a - b, "Random subtraction failed")) return UNITT_E_FAIL;
}
return UNITT_E_OK;
}
// 测试乘法函数,使用随机输入
int test_multiply()
{
// 进行10次随机测试
for (int i = 0; i < SINGLE_TCOUNT; i++)
{
int a = random_input();
int b = random_input();
if (UNITT_E_FAIL == unitt_det_equal(unit_multiply(a, b), a * b, "Random multiplication failed")) return UNITT_E_FAIL;
}
return UNITT_E_OK;
}
// 测试除法函数,使用随机输入
int test_divide()
{
// 进行10次随机测试
for (int i = 0; i < SINGLE_TCOUNT; i++)
{
int a = random_input();
int b = random_input();
if (b != 0)
{
if (UNITT_E_FAIL == unitt_det_float(unit_divide(a, b), (float)a / (float)b, 0.00001, "Random division failed")) return UNITT_E_FAIL;
}
}
return UNITT_E_OK;
}
void unit_main()
{
static UNITT_TCASE math_tests[] = {
UNITT_TCASE(test_add),
UNITT_TCASE(test_subtract),
UNITT_TCASE(test_multiply),
UNITT_TCASE(test_divide),
};
static UNITT suites[] = {
{ "Math Suite", math_tests, sizeof(math_tests) / sizeof(math_tests[0]) , unitt_clock },
};
UNITT_EXE(suites);
}
static void test(void)
{
srand((unsigned int)time(NULL)); // 初始化随机数种子
// unit_main();
printf("create task %d\r\n", task_create(1000, unit_main));
}
init_export_app(test);