BuildSystem: Cleanup userspace directory layout
userspace programs are now in userspace/programs userspace tests are now in userspace/tests This makes listing userspace projects much cleaner. Libraries were already separated to their own directory, so other programs should also.
This commit is contained in:
22
userspace/tests/CMakeLists.txt
Normal file
22
userspace/tests/CMakeLists.txt
Normal file
@@ -0,0 +1,22 @@
|
||||
set(USERSPACE_TESTS
|
||||
test-fork
|
||||
test-framebuffer
|
||||
test-globals
|
||||
test-mmap-shared
|
||||
test-mouse
|
||||
test-popen
|
||||
test-sort
|
||||
test-tcp
|
||||
test-udp
|
||||
test-unix-socket
|
||||
test-window
|
||||
)
|
||||
|
||||
foreach(project ${USERSPACE_TESTS})
|
||||
add_subdirectory(${project})
|
||||
add_dependencies(userspace ${project})
|
||||
# This is to allow cmake to link when libc updates
|
||||
target_link_options(${project} PRIVATE -nolibc)
|
||||
# Default compile options
|
||||
target_compile_options(${project} PRIVATE -g -O2)
|
||||
endforeach()
|
||||
8
userspace/tests/test-fork/CMakeLists.txt
Normal file
8
userspace/tests/test-fork/CMakeLists.txt
Normal file
@@ -0,0 +1,8 @@
|
||||
set(SOURCES
|
||||
main.cpp
|
||||
)
|
||||
|
||||
add_executable(test-fork ${SOURCES})
|
||||
banan_link_library(test-fork libc)
|
||||
|
||||
install(TARGETS test-fork OPTIONAL)
|
||||
22
userspace/tests/test-fork/main.cpp
Normal file
22
userspace/tests/test-fork/main.cpp
Normal file
@@ -0,0 +1,22 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#define ERROR(msg) { perror(msg); return 1; }
|
||||
#define BUF_SIZE 1024
|
||||
|
||||
int main()
|
||||
{
|
||||
printf("userspace\n");
|
||||
|
||||
if (fork() == 0)
|
||||
{
|
||||
execl("/usr/bin/cat", "/usr/bin/cat", "/usr/include/kernel/kprint.h", NULL);
|
||||
ERROR("execl");
|
||||
return 0;
|
||||
}
|
||||
|
||||
printf("parent\n");
|
||||
return 0;
|
||||
}
|
||||
8
userspace/tests/test-framebuffer/CMakeLists.txt
Normal file
8
userspace/tests/test-framebuffer/CMakeLists.txt
Normal file
@@ -0,0 +1,8 @@
|
||||
set(SOURCES
|
||||
main.cpp
|
||||
)
|
||||
|
||||
add_executable(test-framebuffer ${SOURCES})
|
||||
banan_link_library(test-framebuffer libc)
|
||||
|
||||
install(TARGETS test-framebuffer OPTIONAL)
|
||||
45
userspace/tests/test-framebuffer/main.cpp
Normal file
45
userspace/tests/test-framebuffer/main.cpp
Normal file
@@ -0,0 +1,45 @@
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
#include <sys/framebuffer.h>
|
||||
#include <sys/mman.h>
|
||||
|
||||
int main()
|
||||
{
|
||||
int fd = open("/dev/fb0", O_RDWR);
|
||||
if (fd == -1)
|
||||
{
|
||||
perror("open");
|
||||
return 1;
|
||||
}
|
||||
|
||||
framebuffer_info_t fb_info;
|
||||
if (pread(fd, &fb_info, sizeof(fb_info), -1) == -1)
|
||||
{
|
||||
perror("read");
|
||||
return 1;
|
||||
}
|
||||
|
||||
size_t fb_size = fb_info.width * fb_info.height * BANAN_FB_BPP / 8;
|
||||
|
||||
void* addr = mmap(nullptr, fb_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
|
||||
if (addr == MAP_FAILED)
|
||||
{
|
||||
perror("mmap");
|
||||
return 1;
|
||||
}
|
||||
|
||||
memset(addr, 0xFF, fb_size);
|
||||
|
||||
if (msync(addr, fb_size, MS_SYNC) == -1)
|
||||
{
|
||||
perror("msync");
|
||||
return 1;
|
||||
}
|
||||
|
||||
sleep(4);
|
||||
|
||||
munmap(addr, fb_size);
|
||||
close(fd);
|
||||
|
||||
return 0;
|
||||
}
|
||||
8
userspace/tests/test-globals/CMakeLists.txt
Normal file
8
userspace/tests/test-globals/CMakeLists.txt
Normal file
@@ -0,0 +1,8 @@
|
||||
set(SOURCES
|
||||
main.cpp
|
||||
)
|
||||
|
||||
add_executable(test-globals ${SOURCES})
|
||||
banan_link_library(test-globals libc)
|
||||
|
||||
install(TARGETS test-globals OPTIONAL)
|
||||
14
userspace/tests/test-globals/main.cpp
Normal file
14
userspace/tests/test-globals/main.cpp
Normal file
@@ -0,0 +1,14 @@
|
||||
#include <stdio.h>
|
||||
|
||||
struct foo_t
|
||||
{
|
||||
foo_t() { printf("global constructor works\n"); }
|
||||
~foo_t() { printf("global destructor works\n"); }
|
||||
};
|
||||
|
||||
foo_t foo;
|
||||
|
||||
int main()
|
||||
{
|
||||
|
||||
}
|
||||
8
userspace/tests/test-mmap-shared/CMakeLists.txt
Normal file
8
userspace/tests/test-mmap-shared/CMakeLists.txt
Normal file
@@ -0,0 +1,8 @@
|
||||
set(SOURCES
|
||||
main.cpp
|
||||
)
|
||||
|
||||
add_executable(test-mmap-shared ${SOURCES})
|
||||
banan_link_library(test-mmap-shared libc)
|
||||
|
||||
install(TARGETS test-mmap-shared OPTIONAL)
|
||||
197
userspace/tests/test-mmap-shared/main.cpp
Normal file
197
userspace/tests/test-mmap-shared/main.cpp
Normal file
@@ -0,0 +1,197 @@
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#define FILE_NAME "test-file"
|
||||
#define FILE_SIZE (1024*1024)
|
||||
|
||||
int prepare_file()
|
||||
{
|
||||
int fd = open(FILE_NAME, O_RDWR | O_TRUNC | O_CREAT, 0666);
|
||||
if (fd == -1)
|
||||
{
|
||||
perror("open");
|
||||
return 1;
|
||||
}
|
||||
|
||||
void* null_buffer = malloc(FILE_SIZE);
|
||||
memset(null_buffer, 0x00, FILE_SIZE);
|
||||
|
||||
if (write(fd, null_buffer, FILE_SIZE) == -1)
|
||||
{
|
||||
perror("write");
|
||||
return 1;
|
||||
}
|
||||
|
||||
free(null_buffer);
|
||||
close(fd);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int test1_job1()
|
||||
{
|
||||
int fd = open(FILE_NAME, O_RDONLY);
|
||||
if (fd == -1)
|
||||
{
|
||||
perror("open");
|
||||
return 1;
|
||||
}
|
||||
|
||||
void* addr = mmap(nullptr, FILE_SIZE, PROT_READ, MAP_SHARED, fd, 0);
|
||||
if (addr == MAP_FAILED)
|
||||
{
|
||||
perror("mmap");
|
||||
return 1;
|
||||
}
|
||||
|
||||
sleep(4);
|
||||
|
||||
size_t sum = 0;
|
||||
for (int i = 0; i < FILE_SIZE; i++)
|
||||
sum += ((uint8_t*)addr)[i];
|
||||
|
||||
munmap(addr, FILE_SIZE);
|
||||
close(fd);
|
||||
|
||||
printf("got: %zu\n", sum);
|
||||
|
||||
exit(0);
|
||||
}
|
||||
|
||||
int test1_job2()
|
||||
{
|
||||
sleep(2);
|
||||
|
||||
int fd = open(FILE_NAME, O_RDWR);
|
||||
if (fd == -1)
|
||||
{
|
||||
perror("open");
|
||||
return 1;
|
||||
}
|
||||
|
||||
void* addr = mmap(nullptr, FILE_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
|
||||
if (addr == MAP_FAILED)
|
||||
{
|
||||
perror("mmap");
|
||||
return 1;
|
||||
}
|
||||
|
||||
memset(addr, 'a', FILE_SIZE);
|
||||
|
||||
munmap(addr, FILE_SIZE);
|
||||
close(fd);
|
||||
|
||||
printf("expecting: %zu\n", (size_t)'a' * FILE_SIZE);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int test1()
|
||||
{
|
||||
if (int ret = prepare_file())
|
||||
return ret;
|
||||
|
||||
pid_t pid = fork();
|
||||
if (pid == 0)
|
||||
return test1_job1();
|
||||
|
||||
if (pid == -1)
|
||||
{
|
||||
perror("fork");
|
||||
return 1;
|
||||
}
|
||||
|
||||
int ret = test1_job2();
|
||||
waitpid(pid, nullptr, 0);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int test2_job1()
|
||||
{
|
||||
sleep(2);
|
||||
|
||||
int fd = open(FILE_NAME, O_RDWR);
|
||||
if (fd == -1)
|
||||
{
|
||||
perror("open");
|
||||
return 1;
|
||||
}
|
||||
|
||||
size_t value = 0;
|
||||
if (read(fd, &value, sizeof(size_t)) == -1)
|
||||
{
|
||||
perror("read");
|
||||
return 1;
|
||||
}
|
||||
|
||||
printf("got: %zu\n", value);
|
||||
|
||||
close(fd);
|
||||
|
||||
exit(0);
|
||||
}
|
||||
|
||||
int test2_job2()
|
||||
{
|
||||
int fd = open(FILE_NAME, O_RDWR);
|
||||
if (fd == -1)
|
||||
{
|
||||
perror("open");
|
||||
return 1;
|
||||
}
|
||||
|
||||
void* addr = mmap(nullptr, FILE_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
|
||||
if (addr == MAP_FAILED)
|
||||
{
|
||||
perror("mmap");
|
||||
return 1;
|
||||
}
|
||||
|
||||
*(size_t*)addr = 0x12345678;
|
||||
|
||||
if (msync(addr, sizeof(size_t), MS_SYNC) == -1)
|
||||
{
|
||||
perror("msync");
|
||||
return 1;
|
||||
}
|
||||
|
||||
printf("expecting: %zu\n", *(size_t*)addr);
|
||||
|
||||
sleep(4);
|
||||
|
||||
munmap(addr, FILE_SIZE);
|
||||
close(fd);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int test2()
|
||||
{
|
||||
if (int ret = prepare_file())
|
||||
return ret;
|
||||
|
||||
pid_t pid = fork();
|
||||
if (pid == 0)
|
||||
return test2_job1();
|
||||
|
||||
if (pid == -1)
|
||||
{
|
||||
perror("fork");
|
||||
return 1;
|
||||
}
|
||||
|
||||
int ret = test2_job2();
|
||||
waitpid(pid, nullptr, 0);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
test1();
|
||||
test2();
|
||||
}
|
||||
10
userspace/tests/test-mouse/CMakeLists.txt
Normal file
10
userspace/tests/test-mouse/CMakeLists.txt
Normal file
@@ -0,0 +1,10 @@
|
||||
set(SOURCES
|
||||
main.cpp
|
||||
)
|
||||
|
||||
add_executable(test-mouse ${SOURCES})
|
||||
banan_include_headers(test-mouse ban)
|
||||
banan_include_headers(test-mouse libinput)
|
||||
banan_link_library(test-mouse libc)
|
||||
|
||||
install(TARGETS test-mouse OPTIONAL)
|
||||
182
userspace/tests/test-mouse/main.cpp
Normal file
182
userspace/tests/test-mouse/main.cpp
Normal file
@@ -0,0 +1,182 @@
|
||||
#include <BAN/Math.h>
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/framebuffer.h>
|
||||
#include <sys/mman.h>
|
||||
#include <termios.h>
|
||||
|
||||
#include <LibInput/MouseEvent.h>
|
||||
|
||||
framebuffer_info_t fb_info;
|
||||
void* fb_mmap = nullptr;
|
||||
|
||||
int mouse_fd = -1;
|
||||
|
||||
termios original_termios {};
|
||||
|
||||
void draw_circle(int cx, int cy, int r, uint32_t color)
|
||||
{
|
||||
int min_x = BAN::Math::max<int>(cx - r, 0);
|
||||
int max_x = BAN::Math::min<int>(cx + r + 1, fb_info.width);
|
||||
|
||||
int min_y = BAN::Math::max<int>(cy - r, 0);
|
||||
int max_y = BAN::Math::min<int>(cy + r + 1, fb_info.height);
|
||||
|
||||
for (int y = min_y; y < max_y; y++)
|
||||
{
|
||||
for (int x = min_x; x < max_x; x++)
|
||||
{
|
||||
int dx = x - cx;
|
||||
int dy = y - cy;
|
||||
if (dx * dx + dy * dy > r * r)
|
||||
continue;
|
||||
static_cast<uint32_t*>(fb_mmap)[y * fb_info.width + x] = color;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void cleanup()
|
||||
{
|
||||
if (fb_mmap)
|
||||
munmap(fb_mmap, fb_info.height * fb_info.width * (BANAN_FB_BPP / 8));
|
||||
if (mouse_fd != -1)
|
||||
close(mouse_fd);
|
||||
if (original_termios.c_lflag & ECHO)
|
||||
tcsetattr(STDIN_FILENO, TCSANOW, &original_termios);
|
||||
}
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
const char* fb_path = "/dev/fb0";
|
||||
const char* mouse_path = "/dev/input1";
|
||||
|
||||
if (argc == 1)
|
||||
;
|
||||
else if (argc == 3)
|
||||
{
|
||||
fb_path = argv[1];
|
||||
mouse_path = argv[2];
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "usage: %s [FB_PATH MOUSE_PATH]", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
signal(SIGINT, [](int) { exit(0); });
|
||||
if (atexit(cleanup) == -1)
|
||||
{
|
||||
perror("atexit");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (BANAN_FB_BPP != 32)
|
||||
{
|
||||
fprintf(stderr, "unsupported bpp\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
int fb_fd = open(fb_path, O_RDWR);
|
||||
if (fb_fd == -1)
|
||||
{
|
||||
fprintf(stderr, "open: ");
|
||||
perror(fb_path);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (pread(fb_fd, &fb_info, sizeof(fb_info), -1) == -1)
|
||||
{
|
||||
fprintf(stderr, "read: ");
|
||||
perror(fb_path);
|
||||
return 1;
|
||||
}
|
||||
|
||||
size_t fb_bytes = fb_info.width * fb_info.height * (BANAN_FB_BPP / 8);
|
||||
fb_mmap = mmap(nullptr, fb_bytes, PROT_READ | PROT_WRITE, MAP_SHARED, fb_fd, 0);
|
||||
close(fb_fd);
|
||||
if (fb_mmap == MAP_FAILED)
|
||||
{
|
||||
fprintf(stderr, "mmap: ");
|
||||
perror(fb_path);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int mouse_fd = open(mouse_path, O_RDONLY);
|
||||
if (mouse_fd == -1)
|
||||
{
|
||||
fprintf(stderr, "open: ");
|
||||
perror(mouse_path);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (tcgetattr(STDIN_FILENO, &original_termios) == -1)
|
||||
{
|
||||
perror("tcgetattr");
|
||||
return 1;
|
||||
}
|
||||
|
||||
termios termios = original_termios;
|
||||
termios.c_lflag &= ~ECHO;
|
||||
if (tcsetattr(STDIN_FILENO, TCSANOW, &termios) == -1)
|
||||
{
|
||||
perror("tcsetattr");
|
||||
return 1;
|
||||
}
|
||||
|
||||
uint32_t color = 0xFF0000;
|
||||
int mouse_x = fb_info.width / 2;
|
||||
int mouse_y = fb_info.height / 2;
|
||||
int radius = 10;
|
||||
|
||||
// clear screen and render
|
||||
memset(fb_mmap, 0x00, fb_bytes);
|
||||
draw_circle(mouse_x, mouse_y, radius, color);
|
||||
msync(fb_mmap, fb_bytes, MS_SYNC);
|
||||
|
||||
while (true)
|
||||
{
|
||||
using namespace LibInput;
|
||||
|
||||
MouseEvent event;
|
||||
if (read(mouse_fd, &event, sizeof(event)) == -1)
|
||||
{
|
||||
fprintf(stderr, "read: ");
|
||||
perror(mouse_path);
|
||||
return 1;
|
||||
}
|
||||
|
||||
switch (event.type)
|
||||
{
|
||||
case MouseEventType::MouseMoveEvent:
|
||||
draw_circle(mouse_x, mouse_y, radius, 0x000000);
|
||||
mouse_x = BAN::Math::clamp<int>(mouse_x + event.move_event.rel_x, 0, fb_info.width);
|
||||
mouse_y = BAN::Math::clamp<int>(mouse_y - event.move_event.rel_y, 0, fb_info.height);
|
||||
draw_circle(mouse_x, mouse_y, radius, color);
|
||||
break;
|
||||
case MouseEventType::MouseScrollEvent:
|
||||
draw_circle(mouse_x, mouse_y, radius, 0x000000);
|
||||
radius = BAN::Math::clamp(radius + event.scroll_event.scroll, 1, 50);
|
||||
draw_circle(mouse_x, mouse_y, radius, color);
|
||||
break;
|
||||
case MouseEventType::MouseButtonEvent:
|
||||
if (!event.button_event.pressed)
|
||||
break;
|
||||
switch (event.button_event.button)
|
||||
{
|
||||
case MouseButton::Left: color = 0xFF0000; break;
|
||||
case MouseButton::Right: color = 0x00FF00; break;
|
||||
case MouseButton::Middle: color = 0x0000FF; break;
|
||||
case MouseButton::Extra1: color = 0xFFFF00; break;
|
||||
case MouseButton::Extra2: color = 0x00FFFF; break;
|
||||
}
|
||||
draw_circle(mouse_x, mouse_y, radius, color);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
msync(fb_mmap, fb_bytes, MS_SYNC);
|
||||
}
|
||||
}
|
||||
8
userspace/tests/test-popen/CMakeLists.txt
Normal file
8
userspace/tests/test-popen/CMakeLists.txt
Normal file
@@ -0,0 +1,8 @@
|
||||
set(SOURCES
|
||||
main.cpp
|
||||
)
|
||||
|
||||
add_executable(test-popen ${SOURCES})
|
||||
banan_link_library(test-popen libc)
|
||||
|
||||
install(TARGETS test-popen OPTIONAL)
|
||||
30
userspace/tests/test-popen/main.cpp
Normal file
30
userspace/tests/test-popen/main.cpp
Normal file
@@ -0,0 +1,30 @@
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
if (argc != 2)
|
||||
{
|
||||
fprintf(stderr, "usage: %s COMMAND\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
FILE* fp = popen(argv[1], "r");
|
||||
if (fp == nullptr)
|
||||
{
|
||||
perror("popen");
|
||||
return 1;
|
||||
}
|
||||
|
||||
char buffer[128];
|
||||
while (fgets(buffer, sizeof(buffer), fp) != NULL)
|
||||
printf("%s", buffer);
|
||||
|
||||
if (pclose(fp) == -1)
|
||||
{
|
||||
perror("pclose");
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
9
userspace/tests/test-sort/CMakeLists.txt
Normal file
9
userspace/tests/test-sort/CMakeLists.txt
Normal file
@@ -0,0 +1,9 @@
|
||||
set(SOURCES
|
||||
main.cpp
|
||||
)
|
||||
|
||||
add_executable(test-sort ${SOURCES})
|
||||
banan_include_headers(test-sort ban)
|
||||
banan_link_library(test-sort libc)
|
||||
|
||||
install(TARGETS test-sort OPTIONAL)
|
||||
52
userspace/tests/test-sort/main.cpp
Normal file
52
userspace/tests/test-sort/main.cpp
Normal file
@@ -0,0 +1,52 @@
|
||||
#include <BAN/Vector.h>
|
||||
#include <BAN/Sort.h>
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
template<typename T>
|
||||
bool is_sorted(BAN::Vector<T>& vec)
|
||||
{
|
||||
for (size_t i = 0; i < vec.size() - 1; i++)
|
||||
if (vec[i] > vec[i + 1])
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
#define CURRENT_NS() ({ timespec ts; clock_gettime(CLOCK_MONOTONIC, &ts); ts.tv_sec * 1'000'000'000 + ts.tv_nsec; })
|
||||
|
||||
#define TEST_ALGORITHM(ms, function) do { \
|
||||
uint64_t duration_us = 0; \
|
||||
printf(#function "\n"); \
|
||||
for (size_t size = 100; duration_us < ms * 1000; size *= 10) { \
|
||||
BAN::Vector<unsigned> data(size, 0); \
|
||||
for (auto& val : data) \
|
||||
val = rand() % 100; \
|
||||
uint64_t start_ns = CURRENT_NS(); \
|
||||
(void)function(data.begin(), data.end()); \
|
||||
uint64_t stop_ns = CURRENT_NS(); \
|
||||
if (!is_sorted(data)) { \
|
||||
printf(" \e[31mFAILED!\e[m\n"); \
|
||||
break; \
|
||||
} \
|
||||
duration_us = (stop_ns - start_ns) / 1'000; \
|
||||
printf(" %5d.%03d ms (%zu)\n", \
|
||||
(int)(duration_us / 1000), \
|
||||
(int)(duration_us % 1000), \
|
||||
size \
|
||||
); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
int main()
|
||||
{
|
||||
srand(time(0));
|
||||
TEST_ALGORITHM(100, BAN::sort::exchange_sort);
|
||||
TEST_ALGORITHM(100, BAN::sort::quick_sort);
|
||||
TEST_ALGORITHM(100, BAN::sort::insertion_sort);
|
||||
TEST_ALGORITHM(100, BAN::sort::heap_sort);
|
||||
TEST_ALGORITHM(100, BAN::sort::intro_sort);
|
||||
TEST_ALGORITHM(1000, BAN::sort::sort);
|
||||
TEST_ALGORITHM(1000, BAN::sort::radix_sort);
|
||||
}
|
||||
8
userspace/tests/test-tcp/CMakeLists.txt
Normal file
8
userspace/tests/test-tcp/CMakeLists.txt
Normal file
@@ -0,0 +1,8 @@
|
||||
set(SOURCES
|
||||
main.cpp
|
||||
)
|
||||
|
||||
add_executable(test-tcp ${SOURCES})
|
||||
banan_link_library(test-tcp libc)
|
||||
|
||||
install(TARGETS test-tcp OPTIONAL)
|
||||
110
userspace/tests/test-tcp/main.cpp
Normal file
110
userspace/tests/test-tcp/main.cpp
Normal file
@@ -0,0 +1,110 @@
|
||||
#include <arpa/inet.h>
|
||||
#include <netinet/in.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/un.h>
|
||||
#include <unistd.h>
|
||||
|
||||
in_addr_t get_ipv4_address(const char* query)
|
||||
{
|
||||
if (in_addr_t ipv4 = inet_addr(query); ipv4 != (in_addr_t)(-1))
|
||||
return ipv4;
|
||||
|
||||
int socket = ::socket(AF_UNIX, SOCK_SEQPACKET, 0);
|
||||
if (socket == -1)
|
||||
{
|
||||
perror("socket");
|
||||
return -1;
|
||||
}
|
||||
|
||||
sockaddr_un addr;
|
||||
addr.sun_family = AF_UNIX;
|
||||
strcpy(addr.sun_path, "/tmp/resolver.sock");
|
||||
if (connect(socket, (sockaddr*)&addr, sizeof(addr)) == -1)
|
||||
{
|
||||
perror("connect");
|
||||
close(socket);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (send(socket, query, strlen(query), 0) == -1)
|
||||
{
|
||||
perror("send");
|
||||
close(socket);
|
||||
return -1;
|
||||
}
|
||||
|
||||
sockaddr_storage storage;
|
||||
if (recv(socket, &storage, sizeof(storage), 0) == -1)
|
||||
{
|
||||
perror("recv");
|
||||
close(socket);
|
||||
return -1;
|
||||
}
|
||||
|
||||
close(socket);
|
||||
|
||||
return *reinterpret_cast<in_addr_t*>(storage.ss_storage);
|
||||
}
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
if (argc != 2)
|
||||
{
|
||||
fprintf(stderr, "usage: %s IPADDR\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
in_addr_t ipv4 = get_ipv4_address(argv[1]);
|
||||
if (ipv4 == (in_addr_t)(-1))
|
||||
{
|
||||
fprintf(stderr, "could not parse address '%s'\n", argv[1]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int socket = ::socket(AF_INET, SOCK_STREAM, 0);
|
||||
if (socket == -1)
|
||||
{
|
||||
perror("socket");
|
||||
return 1;
|
||||
}
|
||||
|
||||
printf("connecting to %s\n", inet_ntoa({ .s_addr = ipv4 }));
|
||||
|
||||
sockaddr_in server_addr;
|
||||
server_addr.sin_family = AF_INET;
|
||||
server_addr.sin_port = htons(80);
|
||||
server_addr.sin_addr.s_addr = ipv4;
|
||||
if (connect(socket, (sockaddr*)&server_addr, sizeof(server_addr)) == -1)
|
||||
{
|
||||
perror("connect");
|
||||
return 1;
|
||||
}
|
||||
|
||||
char request[128];
|
||||
strcpy(request, "GET / HTTP/1.1\r\n");
|
||||
strcat(request, "Host: "); strcat(request, argv[1]); strcat(request, "\r\n");
|
||||
strcat(request, "Accept: */*\r\n");
|
||||
strcat(request, "Connection: close\r\n");
|
||||
strcat(request, "\r\n");
|
||||
if (send(socket, request, strlen(request), 0) == -1)
|
||||
{
|
||||
perror("send");
|
||||
return 1;
|
||||
}
|
||||
|
||||
char buffer[1024];
|
||||
for (;;)
|
||||
{
|
||||
ssize_t nrecv = recv(socket, buffer, sizeof(buffer), 0);
|
||||
if (nrecv == -1)
|
||||
perror("recv");
|
||||
if (nrecv <= 0)
|
||||
break;
|
||||
write(STDOUT_FILENO, buffer, nrecv);
|
||||
}
|
||||
|
||||
close(socket);
|
||||
return 0;
|
||||
}
|
||||
8
userspace/tests/test-udp/CMakeLists.txt
Normal file
8
userspace/tests/test-udp/CMakeLists.txt
Normal file
@@ -0,0 +1,8 @@
|
||||
set(SOURCES
|
||||
main.cpp
|
||||
)
|
||||
|
||||
add_executable(test-udp ${SOURCES})
|
||||
banan_link_library(test-udp libc)
|
||||
|
||||
install(TARGETS test-udp OPTIONAL)
|
||||
88
userspace/tests/test-udp/main.cpp
Normal file
88
userspace/tests/test-udp/main.cpp
Normal file
@@ -0,0 +1,88 @@
|
||||
#include <arpa/inet.h>
|
||||
#include <netinet/in.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <sys/socket.h>
|
||||
#include <unistd.h>
|
||||
|
||||
int usage(const char* argv0)
|
||||
{
|
||||
fprintf(stderr, "usage: %s [-s|-c] [-a addr] [-p port]\n", argv0);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
bool server = false;
|
||||
uint32_t addr = 0;
|
||||
uint16_t port = 0;
|
||||
|
||||
for (int i = 1; i < argc; i++)
|
||||
{
|
||||
if (strcmp(argv[i], "-s") == 0)
|
||||
server = true;
|
||||
else if (strcmp(argv[i], "-c") == 0)
|
||||
server = false;
|
||||
else if (strcmp(argv[i], "-a") == 0)
|
||||
addr = inet_addr(argv[++i]);
|
||||
else if (strcmp(argv[i], "-p") == 0)
|
||||
sscanf(argv[++i], "%hu", &port);
|
||||
else
|
||||
return usage(argv[0]);
|
||||
}
|
||||
|
||||
int socket = ::socket(AF_INET, SOCK_DGRAM, 0);
|
||||
if (socket == -1)
|
||||
{
|
||||
perror("socket");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (server)
|
||||
{
|
||||
sockaddr_in bind_addr;
|
||||
bind_addr.sin_family = AF_INET;
|
||||
bind_addr.sin_port = htons(port);
|
||||
bind_addr.sin_addr.s_addr = addr;
|
||||
|
||||
if (bind(socket, (sockaddr*)&bind_addr, sizeof(bind_addr)) == -1)
|
||||
{
|
||||
perror("bind");
|
||||
return 1;
|
||||
}
|
||||
|
||||
printf("listening on %s:%hu\n", inet_ntoa(bind_addr.sin_addr), ntohs(bind_addr.sin_port));
|
||||
|
||||
char buffer[1024];
|
||||
sockaddr_in sender;
|
||||
socklen_t sender_len = sizeof(sender);
|
||||
|
||||
if (recvfrom(socket, buffer, sizeof(buffer), 0, (sockaddr*)&sender, &sender_len) == -1)
|
||||
{
|
||||
perror("recvfrom");
|
||||
return 1;
|
||||
}
|
||||
|
||||
printf("received from %s:%hu\n", inet_ntoa(sender.sin_addr), ntohs(sender.sin_port));
|
||||
printf(" %s\n", buffer);
|
||||
}
|
||||
else
|
||||
{
|
||||
const char buffer[] = "Hello from banan-os!";
|
||||
|
||||
sockaddr_in server_addr;
|
||||
server_addr.sin_family = AF_INET;
|
||||
server_addr.sin_port = htons(port);
|
||||
server_addr.sin_addr.s_addr = addr;
|
||||
|
||||
printf("sending to %s:%hu\n", inet_ntoa(server_addr.sin_addr), ntohs(server_addr.sin_port));
|
||||
if (sendto(socket, buffer, sizeof(buffer), 0, (sockaddr*)&server_addr, sizeof(server_addr)) == -1)
|
||||
{
|
||||
perror("sendto");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
close(socket);
|
||||
return 0;
|
||||
}
|
||||
8
userspace/tests/test-unix-socket/CMakeLists.txt
Normal file
8
userspace/tests/test-unix-socket/CMakeLists.txt
Normal file
@@ -0,0 +1,8 @@
|
||||
set(SOURCES
|
||||
main.cpp
|
||||
)
|
||||
|
||||
add_executable(test-unix-socket ${SOURCES})
|
||||
banan_link_library(test-unix-socket libc)
|
||||
|
||||
install(TARGETS test-unix-socket OPTIONAL)
|
||||
200
userspace/tests/test-unix-socket/main.cpp
Normal file
200
userspace/tests/test-unix-socket/main.cpp
Normal file
@@ -0,0 +1,200 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/un.h>
|
||||
#include <sys/wait.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#define SOCK_PATH "/tmp/test.sock"
|
||||
|
||||
int server_connection()
|
||||
{
|
||||
int socket = ::socket(AF_UNIX, SOCK_STREAM, 0);
|
||||
if (socket == -1)
|
||||
{
|
||||
perror("server: socket");
|
||||
return 1;
|
||||
}
|
||||
|
||||
sockaddr_un addr;
|
||||
addr.sun_family = AF_UNIX;
|
||||
strcpy(addr.sun_path, SOCK_PATH);
|
||||
if (bind(socket, (sockaddr*)&addr, sizeof(addr)))
|
||||
{
|
||||
perror("server: bind");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (listen(socket, 0) == -1)
|
||||
{
|
||||
perror("server: listen");
|
||||
return 1;
|
||||
}
|
||||
|
||||
int client = accept(socket, nullptr, nullptr);
|
||||
if (client == -1)
|
||||
{
|
||||
perror("server: accept");
|
||||
return 1;
|
||||
}
|
||||
|
||||
sleep(2);
|
||||
|
||||
char buffer[128];
|
||||
ssize_t nrecv = recv(client, buffer, sizeof(buffer), 0);
|
||||
if (nrecv == -1)
|
||||
{
|
||||
perror("server: recv");
|
||||
return 1;
|
||||
}
|
||||
|
||||
printf("server: read %d bytes\n", (int)nrecv);
|
||||
printf("server: '%s'\n", buffer);
|
||||
|
||||
char message[] = "Hello from server";
|
||||
if (send(client, message, sizeof(message), 0) == -1)
|
||||
{
|
||||
perror("server: send");
|
||||
return 1;
|
||||
}
|
||||
|
||||
close(client);
|
||||
close(socket);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int client_connection()
|
||||
{
|
||||
sleep(1);
|
||||
|
||||
int socket = ::socket(AF_UNIX, SOCK_STREAM, 0);
|
||||
if (socket == -1)
|
||||
{
|
||||
perror("client: socket");
|
||||
return 1;
|
||||
}
|
||||
|
||||
sockaddr_un addr;
|
||||
addr.sun_family = AF_UNIX;
|
||||
strcpy(addr.sun_path, SOCK_PATH);
|
||||
if (connect(socket, (sockaddr*)&addr, sizeof(addr)) == -1)
|
||||
{
|
||||
perror("client: connect");
|
||||
return 1;
|
||||
}
|
||||
|
||||
char message[] = "Hello from client";
|
||||
if (send(socket, message, sizeof(message), 0) == -1)
|
||||
{
|
||||
perror("client: send");
|
||||
return 1;
|
||||
}
|
||||
|
||||
char buffer[128];
|
||||
ssize_t nrecv = recv(socket, buffer, sizeof(buffer), 0);
|
||||
if (nrecv == -1)
|
||||
{
|
||||
perror("client: recv");
|
||||
return 1;
|
||||
}
|
||||
|
||||
printf("client: read %d bytes\n", (int)nrecv);
|
||||
printf("client: '%s'\n", buffer);
|
||||
|
||||
close(socket);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int server_connectionless()
|
||||
{
|
||||
int socket = ::socket(AF_UNIX, SOCK_DGRAM, 0);
|
||||
if (socket == -1)
|
||||
{
|
||||
perror("server: socket");
|
||||
return 1;
|
||||
}
|
||||
|
||||
sockaddr_un addr;
|
||||
addr.sun_family = AF_UNIX;
|
||||
strcpy(addr.sun_path, SOCK_PATH);
|
||||
if (bind(socket, (sockaddr*)&addr, sizeof(addr)))
|
||||
{
|
||||
perror("server: bind");
|
||||
return 1;
|
||||
}
|
||||
|
||||
sleep(2);
|
||||
|
||||
char buffer[128];
|
||||
ssize_t nrecv = recv(socket, buffer, sizeof(buffer), 0);
|
||||
if (nrecv == -1)
|
||||
{
|
||||
perror("server: recv");
|
||||
return 1;
|
||||
}
|
||||
|
||||
close(socket);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int client_connectionless()
|
||||
{
|
||||
sleep(1);
|
||||
|
||||
int socket = ::socket(AF_UNIX, SOCK_DGRAM, 0);
|
||||
if (socket == -1)
|
||||
{
|
||||
perror("client: socket");
|
||||
return 1;
|
||||
}
|
||||
|
||||
sockaddr_un addr;
|
||||
addr.sun_family = AF_UNIX;
|
||||
strcpy(addr.sun_path, SOCK_PATH);
|
||||
char message[] = "Hello from client";
|
||||
if (sendto(socket, message, sizeof(message), 0, (sockaddr*)&addr, sizeof(addr)) == -1)
|
||||
{
|
||||
perror("client: send");
|
||||
return 1;
|
||||
}
|
||||
|
||||
close(socket);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int test_mode(int (*client)(), int (*server)())
|
||||
{
|
||||
pid_t pid = fork();
|
||||
if (pid == -1)
|
||||
{
|
||||
perror("fork");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (pid == 0)
|
||||
exit(server());
|
||||
|
||||
if (int ret = client())
|
||||
{
|
||||
kill(pid, SIGKILL);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ret;
|
||||
waitpid(pid, &ret, 0);
|
||||
|
||||
if (remove(SOCK_PATH) == -1)
|
||||
perror("remove");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
if (test_mode(client_connection, server_connection))
|
||||
return 1;
|
||||
if (test_mode(client_connectionless, server_connectionless))
|
||||
return 2;
|
||||
return 0;
|
||||
}
|
||||
11
userspace/tests/test-window/CMakeLists.txt
Normal file
11
userspace/tests/test-window/CMakeLists.txt
Normal file
@@ -0,0 +1,11 @@
|
||||
set(SOURCES
|
||||
main.cpp
|
||||
)
|
||||
|
||||
add_executable(test-window ${SOURCES})
|
||||
banan_include_headers(test-window ban)
|
||||
banan_include_headers(test-window libinput)
|
||||
banan_link_library(test-window libc)
|
||||
banan_link_library(test-window libgui)
|
||||
|
||||
install(TARGETS test-window OPTIONAL)
|
||||
64
userspace/tests/test-window/main.cpp
Normal file
64
userspace/tests/test-window/main.cpp
Normal file
@@ -0,0 +1,64 @@
|
||||
#include <BAN/Debug.h>
|
||||
|
||||
#include <LibGUI/Window.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
void randomize_color(BAN::UniqPtr<LibGUI::Window>& window)
|
||||
{
|
||||
uint32_t color = ((rand() % 255) << 16) | ((rand() % 255) << 8) | ((rand() % 255) << 0);
|
||||
for (uint32_t y = 0; y < window->height(); y++)
|
||||
for (uint32_t x = 0; x < window->width(); x++)
|
||||
window->set_pixel(x, y, color);
|
||||
window->invalidate();
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
timespec ts;
|
||||
clock_gettime(CLOCK_MONOTONIC, &ts);
|
||||
srand(ts.tv_nsec);
|
||||
|
||||
auto window_or_error = LibGUI::Window::create(300, 200, "test-window");
|
||||
if (window_or_error.is_error())
|
||||
{
|
||||
dprintln("{}", window_or_error.error());
|
||||
return 1;
|
||||
}
|
||||
|
||||
bool running = true;
|
||||
|
||||
auto window = window_or_error.release_value();
|
||||
window->set_close_window_event_callback([&] { running = false; });
|
||||
window->set_mouse_button_event_callback(
|
||||
[&](LibGUI::EventPacket::MouseButtonEvent event)
|
||||
{
|
||||
if (event.pressed && event.button == LibGUI::EventPacket::MouseButton::Left)
|
||||
randomize_color(window);
|
||||
|
||||
const char* button;
|
||||
switch (event.button)
|
||||
{
|
||||
case LibGUI::EventPacket::MouseButton::Left: button = "left"; break;
|
||||
case LibGUI::EventPacket::MouseButton::Right: button = "right"; break;
|
||||
case LibGUI::EventPacket::MouseButton::Middle: button = "middle"; break;
|
||||
case LibGUI::EventPacket::MouseButton::Extra1: button = "extra1"; break;
|
||||
case LibGUI::EventPacket::MouseButton::Extra2: button = "extra2"; break;
|
||||
}
|
||||
dprintln("mouse button '{}' {} at {}, {}", button, event.pressed ? "pressed" : "released", event.x, event.y);
|
||||
}
|
||||
);
|
||||
|
||||
randomize_color(window);
|
||||
|
||||
while (running)
|
||||
{
|
||||
window->poll_events();
|
||||
|
||||
timespec duration;
|
||||
duration.tv_sec = 0;
|
||||
duration.tv_nsec = 16'666'666;
|
||||
nanosleep(&duration, nullptr);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user