Files
versioningcpp/tests/test_all.cpp
T

81 lines
6.9 KiB
C++
Raw Normal View History

#include "versiond/versiond.hpp"
#include <cassert>
#include <cstdio>
#include <cstring>
#include <sstream>
#include <string>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <thread>
#include <vector>
#include <unistd.h>
int main() {
versiond::Config c = versiond::load_config("/tmp/vtest");
versiond::Db db(c.index_file);
versiond::Store st(c.spool_dir);
FILE* f = fopen("/tmp/vt.txt", "w");
fputs("hi", f);
fclose(f);
long long id = versiond::ingest_file(db, st, c, "/tmp/vt.txt");
assert(id > 0);
versiond::ApiResp a = versiond::api_build_response(db, "/api/stats");
assert(a.code == 200);
assert(a.body.find("versions") != std::string::npos);
versiond::ApiResp b = versiond::api_build_response(db, "/api/versions");
assert(b.code == 200);
versiond::ApiResp h = versiond::api_build_response(db, "/");
assert(h.code == 200);
versiond::ApiResp n = versiond::api_build_response(db, "/nope");
assert(n.code == 404);
int sv[2];
assert(socketpair(AF_UNIX, SOCK_STREAM, 0, sv) == 0);
const char* q = "GET /api/stats HTTP/1.0\r\n\r\n";
assert(send(sv[0], q, strlen(q), MSG_NOSIGNAL) > 0);
char buf[4096];
ssize_t k = recv(sv[1], buf, sizeof(buf) - 1, 0);
assert(k > 0 && k < (ssize_t)sizeof(buf));
std::string req(buf, (size_t)(k > 0 ? k : 0));
std::istringstream rs(req);
std::string m, path;
rs >> m >> path;
assert(m == "GET" && path == "/api/stats");
versiond::ApiResp r = versiond::api_build_response(db, path);
std::ostringstream hh;
hh << "HTTP/1.1 " << r.code << " OK\r\nContent-Length: " << r.body.size()
<< "\r\nConnection: close\r\n\r\n";
std::string head = hh.str();
assert(send(sv[1], head.data(), head.size(), MSG_NOSIGNAL) > 0);
assert(send(sv[1], r.body.data(), r.body.size(), MSG_NOSIGNAL) > 0);
shutdown(sv[1], SHUT_WR);
std::string resp;
ssize_t nn;
while ((nn = recv(sv[0], buf, sizeof(buf), 0)) > 0) { assert(nn <= (ssize_t)sizeof(buf)); resp.append(buf, (size_t)nn); }
close(sv[0]);
close(sv[1]);
assert(resp.find("200") != std::string::npos);
assert(resp.find("versions") != std::string::npos);
versiond::ApiResp s = versiond::api_build_response(db, "/api/stats");
std::string full = versiond::api_format_response(s);
auto pos = full.find("Content-Length:");
assert(pos != std::string::npos);
versiond::ApiResp h2 = versiond::api_build_response(db, "/api/health");
assert(h2.code == 200);
versiond::ApiResp b2 = versiond::api_build_response(db, "/api/blobs");
assert(b2.code == 200);
int sv2[2];
assert(socketpair(AF_UNIX, SOCK_STREAM, 0, sv2) == 0);
assert(send(sv2[1], full.data(), full.size(), MSG_NOSIGNAL) == (ssize_t)full.size());
shutdown(sv2[1], SHUT_WR);
std::string got;
ssize_t m2;
while ((m2 = recv(sv2[0], buf, sizeof(buf), 0)) > 0) got.append(buf, (size_t)m2);
close(sv2[0]); close(sv2[1]);
assert(got == full);
{int ls=socket(AF_INET,SOCK_STREAM,0);assert(ls>=0);int o=1;setsockopt(ls,SOL_SOCKET,SO_REUSEADDR,&o,sizeof(o));sockaddr_in sa{};sa.sin_family=AF_INET;sa.sin_addr.s_addr=htonl(INADDR_LOOPBACK);sa.sin_port=htons(0);assert(bind(ls,(sockaddr*)&sa,sizeof(sa))==0);assert(listen(ls,1)==0);sockaddr_in ga{};socklen_t gl=sizeof(ga);assert(getsockname(ls,(sockaddr*)&ga,&gl)==0);int tp=ntohs(ga.sin_port);std::string ef=versiond::api_format_response(versiond::api_build_response(db,"/api/health"));std::thread th([ls,ef]{int fd=accept(ls,nullptr,nullptr);if(fd>=0){char b[1024];(void)recv(fd,b,sizeof(b),0);size_t n=0;while(n<ef.size()){ssize_t w=send(fd,ef.data()+n,ef.size()-n,MSG_NOSIGNAL);if(w<=0)break;n+=(size_t)w;}close(fd);}});int cl=socket(AF_INET,SOCK_STREAM,0);sockaddr_in ca{};ca.sin_family=AF_INET;ca.sin_addr.s_addr=htonl(INADDR_LOOPBACK);ca.sin_port=htons((uint16_t)tp);assert(connect(cl,(sockaddr*)&ca,sizeof(ca))==0);const char*q2="GET /api/health HTTP/1.0\r\n\r\n";assert(send(cl,q2,strlen(q2),MSG_NOSIGNAL)>0);std::string tg;ssize_t tn;while((tn=recv(cl,buf,sizeof(buf),0))>0)tg.append(buf,(size_t)tn);close(cl);close(ls);th.join();assert(tg==ef);}
{int NC=50000; std::string ef2=versiond::api_format_response(versiond::api_build_response(db,"/api/stats")); int ls2=socket(AF_INET,SOCK_STREAM,0); assert(ls2>=0); int o2=1; setsockopt(ls2,SOL_SOCKET,SO_REUSEADDR,&o2,sizeof(o2)); sockaddr_in sa2{}; sa2.sin_family=AF_INET; sa2.sin_addr.s_addr=htonl(INADDR_LOOPBACK); sa2.sin_port=htons(0); assert(bind(ls2,(sockaddr*)&sa2,sizeof(sa2))==0); assert(listen(ls2,2048)==0); sockaddr_in ga2{}; socklen_t gl2=sizeof(ga2); assert(getsockname(ls2,(sockaddr*)&ga2,&gl2)==0); int tp2=ntohs(ga2.sin_port); std::thread srv([ls2,ef2,NC]{ for(int i=0;i<NC;i++){ int fd=accept(ls2,nullptr,nullptr); if(fd<0) break; char b[1024]; (void)recv(fd,b,sizeof(b),0); size_t n=0; while(n<ef2.size()){ ssize_t w=send(fd,ef2.data()+n,ef2.size()-n,MSG_NOSIGNAL); if(w<=0) break; n+=(size_t)w; } close(fd); } }); std::vector<std::string> outs((size_t)NC); std::vector<std::thread> cls; for(int i=0;i<NC;i++){ cls.emplace_back([tp2,&outs,i]{ int cl=socket(AF_INET,SOCK_STREAM,0); assert(cl>=0); sockaddr_in ca{}; ca.sin_family=AF_INET; ca.sin_addr.s_addr=htonl(INADDR_LOOPBACK); ca.sin_port=htons((uint16_t)tp2); assert(connect(cl,(sockaddr*)&ca,sizeof(ca))==0); const char* q="GET /api/stats HTTP/1.0\r\n\r\n"; assert(send(cl,q,strlen(q),MSG_NOSIGNAL)>0); char bb[4096]; ssize_t tn; while((tn=recv(cl,bb,sizeof(bb),0))>0) outs[(size_t)i].append(bb,(size_t)tn); close(cl); }); } for(auto& th: cls) th.join(); close(ls2); srv.join(); for(auto& s: outs) assert(s==ef2); }
{int NC=50000; std::string ef2=versiond::api_format_response(versiond::api_build_response(db,"/api/stats")); int ls2=socket(AF_INET,SOCK_STREAM,0); assert(ls2>=0); int o2=1; setsockopt(ls2,SOL_SOCKET,SO_REUSEADDR,&o2,sizeof(o2)); sockaddr_in sa2{}; sa2.sin_family=AF_INET; sa2.sin_addr.s_addr=htonl(INADDR_LOOPBACK); sa2.sin_port=htons(0); assert(bind(ls2,(sockaddr*)&sa2,sizeof(sa2))==0); assert(listen(ls2,2048)==0); sockaddr_in ga2{}; socklen_t gl2=sizeof(ga2); assert(getsockname(ls2,(sockaddr*)&ga2,&gl2)==0); int tp2=ntohs(ga2.sin_port); std::thread srv([ls2,ef2,NC]{ for(int i=0;i<NC;i++){ int fd=accept(ls2,nullptr,nullptr); if(fd<0) break; char b[1024]; (void)recv(fd,b,sizeof(b),0); size_t n=0; while(n<ef2.size()){ ssize_t w=send(fd,ef2.data()+n,ef2.size()-n,MSG_NOSIGNAL); if(w<=0) break; n+=(size_t)w; } close(fd); } }); std::vector<std::string> outs((size_t)NC); std::vector<std::thread> cls; for(int i=0;i<NC;i++){ cls.emplace_back([tp2,&outs,i]{ int cl=socket(AF_INET,SOCK_STREAM,0); assert(cl>=0); sockaddr_in ca{}; ca.sin_family=AF_INET; ca.sin_addr.s_addr=htonl(INADDR_LOOPBACK); ca.sin_port=htons((uint16_t)tp2); assert(connect(cl,(sockaddr*)&ca,sizeof(ca))==0); const char* q="GET /api/stats HTTP/1.0\r\n\r\n"; assert(send(cl,q,strlen(q),MSG_NOSIGNAL)>0); char bb[4096]; ssize_t tn; while((tn=recv(cl,bb,sizeof(bb),0))>0) outs[(size_t)i].append(bb,(size_t)tn); close(cl); }); } for(auto& th: cls) th.join(); close(ls2); srv.join(); for(auto& s: outs) assert(s==ef2); }
printf("ok http-smoke live\n");
return 0;
}