Github User Fetcher 1.0.0
C Application with Server and GUI
Loading...
Searching...
No Matches
test_cli.cpp File Reference
#include <array>
#include <chrono>
#include <cstdio>
#include <curl/curl.h>
#include <doctest.h>
#include <functional>
#include <iostream>
#include <memory>
#include <nlohmann/json.hpp>
#include <stdexcept>
#include <string>
#include <thread>

Go to the source code of this file.

Macros

#define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN
 

Functions

std::string run_command (const std::string &cmd)
 
std::string http_get (const std::string &url)
 
bool wait_for_server (int max_retries=10)
 
void stop_server ()
 
 TEST_CASE ("Default user fetch")
 
 TEST_CASE ("Custom user fetch (wycats)")
 
 TEST_CASE ("Run server mode and fetch user data")
 

Macro Definition Documentation

◆ DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN

#define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN

Definition at line 1 of file test_cli.cpp.

Function Documentation

◆ http_get()

std::string http_get ( const std::string & url)

Definition at line 36 of file test_cli.cpp.

36 {
37 CURL *curl = curl_easy_init();
38 if (!curl)
39 throw std::runtime_error("Failed to init curl");
40
41 std::string response;
42 curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
44 curl, CURLOPT_WRITEFUNCTION,
45 +[](char *ptr, size_t size, size_t nmemb, void *userdata) -> size_t {
46 std::string *resp = static_cast<std::string *>(userdata);
47 resp->append(ptr, size * nmemb);
48 return size * nmemb;
49 });
50 curl_easy_setopt(curl, CURLOPT_WRITEDATA, &response);
51
52 CURLcode res = curl_easy_perform(curl);
53 if (res != CURLE_OK) {
55 throw std::runtime_error("CURL request failed: " +
56 std::string(curl_easy_strerror(res)));
57 }
58
60 return response;
61}
void CURL
Definition curl.h:117
CURLcode
Definition curl.h:509
@ CURLE_OK
Definition curl.h:510
CURL_EXTERN const char * curl_easy_strerror(CURLcode)
CURL_EXTERN void curl_easy_cleanup(CURL *curl)
CURL_EXTERN CURLcode curl_easy_perform(CURL *curl)
CURL_EXTERN CURL * curl_easy_init(void)
#define curl_easy_setopt(handle, option, value)

References curl_easy_cleanup(), curl_easy_init(), curl_easy_perform(), curl_easy_setopt, curl_easy_strerror(), and CURLE_OK.

Referenced by TEST_CASE(), and wait_for_server().

◆ run_command()

std::string run_command ( const std::string & cmd)

Definition at line 16 of file test_cli.cpp.

16 {
17 std::array<char, 128> buffer;
18 std::string result;
19
20 // Use std::function to manage the deleter for pclose
21 std::unique_ptr<FILE, std::function<void(FILE *)>> pipe(
22 popen(cmd.c_str(), "r"), [](FILE *f) { pclose(f); });
23
24 if (!pipe)
25 throw std::runtime_error("popen() failed");
26
27 while (fgets(buffer.data(), buffer.size(), pipe.get()) != nullptr) {
28 result += buffer.data();
29 }
30
31 return result;
32}

Referenced by TEST_CASE(), and TEST_CASE().

◆ stop_server()

void stop_server ( )

Definition at line 75 of file test_cli.cpp.

75 {
76 int ret = system("pkill -f 'github_user_fetcher --server'");
77 if (ret != 0) {
78 std::cerr << "Warning: Failed to stop server process\n";
79 }
80}

Referenced by TEST_CASE().

◆ TEST_CASE() [1/3]

TEST_CASE ( "Custom user fetch (wycats)" )

Definition at line 95 of file test_cli.cpp.

95 {
96 std::string output = run_command("./github_user_fetcher --user wycats");
97
98 std::cout << "Output for custom user fetch (wycats):\n"
99 << output << std::endl;
100
101 CHECK(output.find("Login: wycats") != std::string::npos);
102}
#define CHECK(...)
Definition doctest.h:2970
static const char * output
std::string run_command(const std::string &cmd)
Definition test_cli.cpp:16

References CHECK, output, and run_command().

◆ TEST_CASE() [2/3]

TEST_CASE ( "Default user fetch" )

Definition at line 82 of file test_cli.cpp.

82 {
83 std::string output = run_command("./github_user_fetcher");
84
85 // Print the output for debugging purposes
86 std::cout << "Output for default user fetch:\n" << output << std::endl;
87
88 // Check if other specific information is in the output
89 CHECK(output.find("Login: izelnakri") != std::string::npos);
90 CHECK(output.find("Name: Izel Nakri") != std::string::npos);
91 CHECK(output.find("Company: Ruby, JavaScript") != std::string::npos);
92 CHECK(output.find("Location: Madrid") != std::string::npos);
93}

References CHECK, output, and run_command().

◆ TEST_CASE() [3/3]

TEST_CASE ( "Run server mode and fetch user data" )

Definition at line 104 of file test_cli.cpp.

104 {
105 // Run the server in a background thread
106 std::thread server_thread([]() {
107 int ret = system("./github_user_fetcher --server");
108 if (ret != 0) {
109 std::cerr << "Server exited with code: " << ret << std::endl;
110 }
111 });
112
113 // Allow the server some time to start
115
116 try {
117 // Make the HTTP request to the server for the `izelnakri` user
118 std::string url = "http://localhost:1234/izelnakri";
119 std::string json_response = http_get(url);
120
121 // Parse the JSON response
122 auto json = nlohmann::json::parse(json_response);
123
124 // Check that the response contains the expected fields
125 CHECK(json["login"] == "izelnakri");
126 CHECK(json["name"] == "Izel Nakri | izelnakri.eth");
127 CHECK(json["company"] ==
128 "Ruby, JavaScript, TS, elixir, rust, k8s, lua, nix, pkl, android");
129 CHECK(json["location"] == "Madrid | Amsterdam");
130
131 json_response = http_get("http://localhost:1234/wycats");
132 json = nlohmann::json::parse(json_response);
133
134 // Check that the response contains the expected fields for `wycats`
135 CHECK(json["login"] == "wycats");
136 } catch (const std::exception &e) {
137 // If there was an error in any of the steps, make sure the server is
138 // stopped
139 std::cerr << "Test failed: " << e.what() << std::endl;
140 stop_server();
141 MESSAGE("Test failed: ", e.what());
142 FAIL_CHECK("Exception was thrown");
143 }
144
145 // Ensure the server is stopped after the test
146 stop_server();
147
148 if (server_thread.joinable())
149 server_thread.detach(); // Don't join, since we already stopped it
150}
#define FAIL_CHECK(...)
Definition doctest.h:2959
#define MESSAGE(...)
Definition doctest.h:2958
void stop_server()
Definition test_cli.cpp:75
bool wait_for_server(int max_retries=10)
Definition test_cli.cpp:63
std::string http_get(const std::string &url)
Definition test_cli.cpp:36

References CHECK, FAIL_CHECK, http_get(), MESSAGE, stop_server(), and wait_for_server().

◆ wait_for_server()

bool wait_for_server ( int max_retries = 10)

Definition at line 63 of file test_cli.cpp.

63 {
64 for (int i = 0; i < max_retries; ++i) {
65 try {
66 std::string res = http_get("http://localhost:1234/wycats");
67 return !res.empty();
68 } catch (...) {
69 std::this_thread::sleep_for(std::chrono::milliseconds(300));
70 }
71 }
72 return false;
73}

References http_get().

Referenced by TEST_CASE().