mirror of
https://github.com/sunnypilot/sunnypilot.git
synced 2026-10-01 03:53:45 +08:00
replace catch2 tests for 20% faster builds (#38408)
* replace catch2 tests * lil more * lil more * rm dep!
This commit is contained in:
+1
-1
@@ -55,7 +55,7 @@ assert arch in [
|
||||
"Darwin", # macOS arm64 (x86 not supported)
|
||||
]
|
||||
|
||||
pkg_names = ['acados', 'bzip2', 'capnproto', 'catch2', 'ffmpeg', 'json11', 'ncurses', 'zeromq', 'zstd']
|
||||
pkg_names = ['acados', 'bzip2', 'capnproto', 'ffmpeg', 'json11', 'ncurses', 'zeromq', 'zstd']
|
||||
pkgs = [importlib.import_module(name) for name in pkg_names]
|
||||
acados = pkgs[pkg_names.index('acados')]
|
||||
ffmpeg = pkgs[pkg_names.index('ffmpeg')]
|
||||
|
||||
+1
-1
Submodule msgq_repo updated: a771d031ec...6a8d2e8f06
@@ -12,9 +12,7 @@ _common = env.Library('common', common_libs, LIBS="json11")
|
||||
Export('_common')
|
||||
|
||||
if GetOption('extras'):
|
||||
env.Program('tests/test_common',
|
||||
['tests/test_runner.cc', 'tests/test_util.cc', 'tests/test_swaglog.cc'],
|
||||
LIBS=[_common, 'json11', 'zmq', 'pthread'])
|
||||
env.Program('tests/test_swaglog', 'tests/test_swaglog.cc', LIBS=[_common, 'json11', 'zmq', 'pthread'])
|
||||
|
||||
# Cython bindings
|
||||
params_python = envCython.Program('params_pyx.so', 'params_pyx.pyx', LIBS=envCython['LIBS'] + [_common, 'zmq', 'json11'])
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
#pragma once
|
||||
|
||||
#include <iostream>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
|
||||
inline void native_test_check(bool condition, const char *expression, const char *file, int line) {
|
||||
if (!condition) {
|
||||
throw std::runtime_error(std::string(file) + ":" + std::to_string(line) + ": check failed: " + expression);
|
||||
}
|
||||
}
|
||||
|
||||
#define CHECK(condition) native_test_check(static_cast<bool>(condition), #condition, __FILE__, __LINE__)
|
||||
#define REQUIRE(...) CHECK((__VA_ARGS__))
|
||||
|
||||
template <typename Function>
|
||||
int run_native_test(Function &&function) {
|
||||
try {
|
||||
function();
|
||||
return 0;
|
||||
} catch (const std::exception &error) {
|
||||
std::cerr << error.what() << '\n';
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
@@ -1,2 +0,0 @@
|
||||
#define CATCH_CONFIG_MAIN
|
||||
#include "catch2/catch.hpp"
|
||||
@@ -1,88 +1,47 @@
|
||||
#include <cstdlib>
|
||||
#include <string>
|
||||
|
||||
#include <zmq.h>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include "catch2/catch.hpp"
|
||||
#include "common/swaglog.h"
|
||||
#include "common/util.h"
|
||||
#include "common/version.h"
|
||||
#include "common/hardware/hw.h"
|
||||
#include "common/swaglog.h"
|
||||
#include "common/tests/native_test.h"
|
||||
#include "json11/json11.hpp"
|
||||
|
||||
std::string daemon_name = "testy";
|
||||
std::string dongle_id = "test_dongle_id";
|
||||
int LINE_NO = 0;
|
||||
void test_swaglog() {
|
||||
setenv("MANAGER_DAEMON", "swaglog_test", 1);
|
||||
setenv("DONGLE_ID", "test_dongle_id", 1);
|
||||
setenv("CLEAN", "1", 1);
|
||||
|
||||
void log_thread(int thread_id, int msg_cnt) {
|
||||
for (int i = 0; i < msg_cnt; ++i) {
|
||||
LOGD("%d", thread_id);
|
||||
LINE_NO = __LINE__ - 1;
|
||||
usleep(1);
|
||||
}
|
||||
void *context = zmq_ctx_new();
|
||||
CHECK(context != nullptr);
|
||||
void *socket = zmq_socket(context, ZMQ_PULL);
|
||||
CHECK(socket != nullptr);
|
||||
int timeout = 5000;
|
||||
CHECK(zmq_setsockopt(socket, ZMQ_RCVTIMEO, &timeout, sizeof(timeout)) == 0);
|
||||
CHECK(zmq_bind(socket, Path::swaglog_ipc().c_str()) == 0);
|
||||
|
||||
LOGD("native-cpp-log");
|
||||
|
||||
char buffer[4096] = {};
|
||||
const int size = zmq_recv(socket, buffer, sizeof(buffer), 0);
|
||||
CHECK(size > 1);
|
||||
CHECK(buffer[0] == CLOUDLOG_DEBUG);
|
||||
std::string error;
|
||||
const auto message = json11::Json::parse(std::string(buffer + 1, size - 1), error);
|
||||
CHECK(error.empty());
|
||||
CHECK(message["levelnum"].int_value() == CLOUDLOG_DEBUG);
|
||||
CHECK(message["msg"].string_value() == "native-cpp-log");
|
||||
CHECK(message["funcname"].string_value() == "test_swaglog");
|
||||
CHECK(message["filename"].string_value().find("test_swaglog.cc") != std::string::npos);
|
||||
CHECK(message["ctx"]["daemon"].string_value() == "swaglog_test");
|
||||
CHECK(message["ctx"]["dongle_id"].string_value() == "test_dongle_id");
|
||||
CHECK(message["ctx"]["dirty"].bool_value() == false);
|
||||
|
||||
CHECK(zmq_close(socket) == 0);
|
||||
CHECK(zmq_ctx_destroy(context) == 0);
|
||||
}
|
||||
|
||||
void recv_log(int thread_cnt, int thread_msg_cnt) {
|
||||
void *zctx = zmq_ctx_new();
|
||||
void *sock = zmq_socket(zctx, ZMQ_PULL);
|
||||
zmq_bind(sock, Path::swaglog_ipc().c_str());
|
||||
std::vector<int> thread_msgs(thread_cnt);
|
||||
int total_count = 0;
|
||||
|
||||
for (auto start = std::chrono::steady_clock::now(), now = start;
|
||||
now < start + std::chrono::seconds{1} && total_count < (thread_cnt * thread_msg_cnt);
|
||||
now = std::chrono::steady_clock::now()) {
|
||||
char buf[4096] = {};
|
||||
if (zmq_recv(sock, buf, sizeof(buf), ZMQ_DONTWAIT) <= 0) {
|
||||
if (errno == EAGAIN || errno == EINTR || errno == EFSM) continue;
|
||||
break;
|
||||
}
|
||||
|
||||
REQUIRE(buf[0] == CLOUDLOG_DEBUG);
|
||||
std::string err;
|
||||
auto msg = json11::Json::parse(buf + 1, err);
|
||||
REQUIRE(!msg.is_null());
|
||||
|
||||
REQUIRE(msg["levelnum"].int_value() == CLOUDLOG_DEBUG);
|
||||
REQUIRE_THAT(msg["filename"].string_value(), Catch::Contains("test_swaglog.cc"));
|
||||
REQUIRE(msg["funcname"].string_value() == "log_thread");
|
||||
REQUIRE(msg["lineno"].int_value() == LINE_NO);
|
||||
|
||||
auto ctx = msg["ctx"];
|
||||
|
||||
REQUIRE(ctx["daemon"].string_value() == daemon_name);
|
||||
REQUIRE(ctx["dongle_id"].string_value() == dongle_id);
|
||||
REQUIRE(ctx["dirty"].bool_value() == true);
|
||||
|
||||
REQUIRE(ctx["version"].string_value() == COMMA_VERSION);
|
||||
|
||||
std::string device = Hardware::get_name();
|
||||
REQUIRE(ctx["device"].string_value() == device);
|
||||
|
||||
int thread_id = atoi(msg["msg"].string_value().c_str());
|
||||
REQUIRE((thread_id >= 0 && thread_id < thread_cnt));
|
||||
thread_msgs[thread_id]++;
|
||||
total_count++;
|
||||
}
|
||||
for (int i = 0; i < thread_cnt; ++i) {
|
||||
INFO("thread :" << i);
|
||||
REQUIRE(thread_msgs[i] == thread_msg_cnt);
|
||||
}
|
||||
zmq_close(sock);
|
||||
zmq_ctx_destroy(zctx);
|
||||
}
|
||||
|
||||
TEST_CASE("swaglog") {
|
||||
setenv("MANAGER_DAEMON", daemon_name.c_str(), 1);
|
||||
setenv("DONGLE_ID", dongle_id.c_str(), 1);
|
||||
setenv("dirty", "1", 1);
|
||||
const int thread_cnt = 5;
|
||||
const int thread_msg_cnt = 100;
|
||||
|
||||
std::vector<std::thread> log_threads;
|
||||
for (int i = 0; i < thread_cnt; ++i) {
|
||||
log_threads.push_back(std::thread(log_thread, i, thread_msg_cnt));
|
||||
}
|
||||
for (auto &t : log_threads) t.join();
|
||||
|
||||
recv_log(thread_cnt, thread_msg_cnt);
|
||||
int main() {
|
||||
return run_native_test(test_swaglog);
|
||||
}
|
||||
|
||||
@@ -1,147 +0,0 @@
|
||||
|
||||
#include <dirent.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <climits>
|
||||
#include <fstream>
|
||||
#include <random>
|
||||
#include <string>
|
||||
|
||||
#include "catch2/catch.hpp"
|
||||
#include "common/util.h"
|
||||
|
||||
std::string random_bytes(int size) {
|
||||
std::random_device rd;
|
||||
std::independent_bits_engine<std::default_random_engine, CHAR_BIT, unsigned char> rbe(rd());
|
||||
std::string bytes(size + 1, '\0');
|
||||
std::generate(bytes.begin(), bytes.end(), std::ref(rbe));
|
||||
return bytes;
|
||||
}
|
||||
|
||||
TEST_CASE("util::read_file") {
|
||||
SECTION("read /proc/version") {
|
||||
std::string ret = util::read_file("/proc/version");
|
||||
REQUIRE(ret.find("Linux version") != std::string::npos);
|
||||
}
|
||||
SECTION("read from sysfs") {
|
||||
std::string ret = util::read_file("/sys/power/wakeup_count");
|
||||
REQUIRE(!ret.empty());
|
||||
}
|
||||
SECTION("read file") {
|
||||
char filename[] = "/tmp/test_read_XXXXXX";
|
||||
int fd = mkstemp(filename);
|
||||
|
||||
REQUIRE(util::read_file(filename).empty());
|
||||
|
||||
std::string content = random_bytes(64 * 1024);
|
||||
REQUIRE(write(fd, content.c_str(), content.size()) == (ssize_t)content.size());
|
||||
std::string ret = util::read_file(filename);
|
||||
bool equal = (ret == content);
|
||||
REQUIRE(equal);
|
||||
close(fd);
|
||||
}
|
||||
SECTION("read directory") {
|
||||
REQUIRE(util::read_file(".").empty());
|
||||
}
|
||||
SECTION("read non-existent file") {
|
||||
std::string ret = util::read_file("does_not_exist");
|
||||
REQUIRE(ret.empty());
|
||||
}
|
||||
SECTION("read non-permission") {
|
||||
REQUIRE(util::read_file("/proc/kmsg").empty());
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("util::file_exists") {
|
||||
char filename[] = "/tmp/test_file_exists_XXXXXX";
|
||||
int fd = mkstemp(filename);
|
||||
REQUIRE(fd != -1);
|
||||
close(fd);
|
||||
|
||||
SECTION("existent file") {
|
||||
REQUIRE(util::file_exists(filename));
|
||||
REQUIRE(util::file_exists("/tmp"));
|
||||
}
|
||||
SECTION("nonexistent file") {
|
||||
std::string fn = filename;
|
||||
REQUIRE(!util::file_exists(fn + "/nonexistent"));
|
||||
}
|
||||
SECTION("file has no access permissions") {
|
||||
std::string fn = "/proc/kmsg";
|
||||
std::ifstream f(fn);
|
||||
REQUIRE(f.good() == false);
|
||||
REQUIRE(util::file_exists(fn));
|
||||
}
|
||||
::remove(filename);
|
||||
}
|
||||
|
||||
TEST_CASE("util::read_files_in_dir") {
|
||||
char tmp_path[] = "/tmp/test_XXXXXX";
|
||||
const std::string test_path = mkdtemp(tmp_path);
|
||||
const std::string files[] = {".test1", "'test2'", "test3"};
|
||||
for (auto fn : files) {
|
||||
std::ofstream{test_path + "/" + fn} << fn;
|
||||
}
|
||||
mkdir((test_path + "/dir").c_str(), 0777);
|
||||
|
||||
std::map<std::string, std::string> result = util::read_files_in_dir(test_path);
|
||||
REQUIRE(result.find("dir") == result.end());
|
||||
REQUIRE(result.size() == std::size(files));
|
||||
for (auto& [k, v] : result) {
|
||||
REQUIRE(k == v);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
TEST_CASE("util::safe_fwrite") {
|
||||
char filename[] = "/tmp/XXXXXX";
|
||||
int fd = mkstemp(filename);
|
||||
close(fd);
|
||||
std::string dat = random_bytes(1024 * 1024);
|
||||
|
||||
FILE *f = util::safe_fopen(filename, "wb");
|
||||
REQUIRE(f != nullptr);
|
||||
size_t size = util::safe_fwrite(dat.data(), 1, dat.size(), f);
|
||||
REQUIRE(size == dat.size());
|
||||
int ret = util::safe_fflush(f);
|
||||
REQUIRE(ret == 0);
|
||||
ret = fclose(f);
|
||||
REQUIRE(ret == 0);
|
||||
bool equal = (dat == util::read_file(filename));
|
||||
REQUIRE(equal);
|
||||
}
|
||||
|
||||
TEST_CASE("util::create_directories") {
|
||||
REQUIRE(system("rm /tmp/test_create_directories -rf") == 0);
|
||||
std::string dir = "/tmp/test_create_directories/a/b/c/d/e/f";
|
||||
|
||||
auto check_dir_permissions = [](const std::string &path, mode_t mode) -> bool {
|
||||
struct stat st = {};
|
||||
return stat(path.c_str(), &st) == 0 && (st.st_mode & S_IFMT) == S_IFDIR && (st.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO)) == mode;
|
||||
};
|
||||
|
||||
SECTION("create_directories") {
|
||||
REQUIRE(util::create_directories(dir, 0755));
|
||||
REQUIRE(check_dir_permissions(dir, 0755));
|
||||
}
|
||||
SECTION("dir already exists") {
|
||||
REQUIRE(util::create_directories(dir, 0755));
|
||||
REQUIRE(util::create_directories(dir, 0755));
|
||||
}
|
||||
SECTION("a file exists with the same name") {
|
||||
REQUIRE(util::create_directories(dir, 0755));
|
||||
int f = open((dir + "/file").c_str(), O_RDWR | O_CREAT, 0644);
|
||||
REQUIRE(f != -1);
|
||||
close(f);
|
||||
REQUIRE(util::create_directories(dir + "/file", 0755) == false);
|
||||
REQUIRE(util::create_directories(dir + "/file/1/2/3", 0755) == false);
|
||||
}
|
||||
SECTION("end with slashes") {
|
||||
REQUIRE(util::create_directories(dir + "/", 0755));
|
||||
}
|
||||
SECTION("empty") {
|
||||
REQUIRE(util::create_directories("", 0755) == false);
|
||||
}
|
||||
}
|
||||
@@ -1,11 +1,7 @@
|
||||
#define CATCH_CONFIG_MAIN
|
||||
#define CATCH_CONFIG_ENABLE_BENCHMARKING
|
||||
|
||||
#include <climits>
|
||||
|
||||
#include "catch2/catch.hpp"
|
||||
#include "common/tests/native_test.h"
|
||||
#include "openpilot/cereal/messaging/messaging.h"
|
||||
#include "common/util.h"
|
||||
#include "selfdrive/pandad/panda.h"
|
||||
|
||||
struct PandaTest : public Panda {
|
||||
@@ -26,12 +22,9 @@ PandaTest::PandaTest(int can_list_size_, cereal::PandaState::PandaType hw_type_)
|
||||
int data_limit = ((hw_type == cereal::PandaState::PandaType::RED_PANDA) ? std::size(dlc_to_len) : 8);
|
||||
// prepare test data
|
||||
for (int i = 0; i < data_limit; ++i) {
|
||||
std::random_device rd;
|
||||
std::independent_bits_engine<std::default_random_engine, CHAR_BIT, unsigned char> rbe(rd());
|
||||
|
||||
int data_len = dlc_to_len[i];
|
||||
std::string bytes(data_len, '\0');
|
||||
std::generate(bytes.begin(), bytes.end(), std::ref(rbe));
|
||||
for (int j = 0; j < data_len; ++j) bytes[j] = static_cast<char>((i * 31 + j) & 0xff);
|
||||
test_data[data_len] = bytes;
|
||||
}
|
||||
|
||||
@@ -39,16 +32,15 @@ PandaTest::PandaTest(int can_list_size_, cereal::PandaState::PandaType hw_type_)
|
||||
auto can_list = msg.initEvent().initSendcan(can_list_size);
|
||||
for (uint8_t i = 0; i < can_list_size; ++i) {
|
||||
auto can = can_list[i];
|
||||
uint32_t id = util::random_int(0, std::size(dlc_to_len) - 1);
|
||||
uint32_t id = i % data_limit;
|
||||
const std::string &dat = test_data[dlc_to_len[id]];
|
||||
can.setAddress(i);
|
||||
can.setSrc(util::random_int(0, 2));
|
||||
can.setSrc(i % 3);
|
||||
can.setDat(kj::ArrayPtr((uint8_t *)dat.data(), dat.size()));
|
||||
total_pakets_size += sizeof(can_header) + dat.size();
|
||||
}
|
||||
|
||||
can_data_list = can_list.asReader();
|
||||
INFO("test " << can_list_size << " packets, total size " << total_pakets_size);
|
||||
}
|
||||
|
||||
void PandaTest::test_can_send() {
|
||||
@@ -56,30 +48,29 @@ void PandaTest::test_can_send() {
|
||||
this->pack_can_buffer(can_data_list, [&](uint8_t *chunk, size_t size) {
|
||||
unpacked_data.insert(unpacked_data.end(), chunk, &chunk[size]);
|
||||
});
|
||||
REQUIRE(unpacked_data.size() == total_pakets_size);
|
||||
CHECK(unpacked_data.size() == total_pakets_size);
|
||||
|
||||
int cnt = 0;
|
||||
INFO("test can message integrity");
|
||||
for (int pos = 0, pckt_len = 0; pos < unpacked_data.size(); pos += pckt_len) {
|
||||
can_header header;
|
||||
memcpy(&header, &unpacked_data[pos], sizeof(can_header));
|
||||
const uint8_t data_len = dlc_to_len[header.data_len_code];
|
||||
pckt_len = sizeof(can_header) + data_len;
|
||||
|
||||
REQUIRE(header.addr == cnt);
|
||||
REQUIRE(test_data.find(data_len) != test_data.end());
|
||||
CHECK(header.addr == cnt);
|
||||
CHECK(test_data.find(data_len) != test_data.end());
|
||||
const std::string &dat = test_data[data_len];
|
||||
REQUIRE(memcmp(dat.data(), &unpacked_data[pos + sizeof(can_header)], dat.size()) == 0);
|
||||
CHECK(memcmp(dat.data(), &unpacked_data[pos + sizeof(can_header)], dat.size()) == 0);
|
||||
++cnt;
|
||||
}
|
||||
REQUIRE(cnt == can_list_size);
|
||||
CHECK(cnt == can_list_size);
|
||||
}
|
||||
|
||||
void PandaTest::test_can_recv(uint32_t rx_chunk_size) {
|
||||
std::vector<can_frame> frames;
|
||||
this->pack_can_buffer(can_data_list, [&](uint8_t *data, uint32_t size) {
|
||||
if (rx_chunk_size == 0) {
|
||||
REQUIRE(this->unpack_can_buffer(data, size, frames));
|
||||
CHECK(this->unpack_can_buffer(data, size, frames));
|
||||
} else {
|
||||
this->receive_buffer_size = 0;
|
||||
uint32_t pos = 0;
|
||||
@@ -90,46 +81,35 @@ void PandaTest::test_can_recv(uint32_t rx_chunk_size) {
|
||||
this->receive_buffer_size += chunk_size;
|
||||
pos += chunk_size;
|
||||
|
||||
REQUIRE(this->unpack_can_buffer(this->receive_buffer, this->receive_buffer_size, frames));
|
||||
CHECK(this->unpack_can_buffer(this->receive_buffer, this->receive_buffer_size, frames));
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
REQUIRE(frames.size() == can_list_size);
|
||||
CHECK(frames.size() == can_list_size);
|
||||
for (int i = 0; i < frames.size(); ++i) {
|
||||
REQUIRE(frames[i].address == i);
|
||||
REQUIRE(test_data.find(frames[i].dat.size()) != test_data.end());
|
||||
CHECK(frames[i].address == i);
|
||||
CHECK(test_data.find(frames[i].dat.size()) != test_data.end());
|
||||
const std::string &dat = test_data[frames[i].dat.size()];
|
||||
REQUIRE(memcmp(dat.data(), frames[i].dat.data(), dat.size()) == 0);
|
||||
CHECK(memcmp(dat.data(), frames[i].dat.data(), dat.size()) == 0);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("send/recv CAN 2.0 packets") {
|
||||
auto can_list_size = GENERATE(1, 3, 5, 10, 30, 60, 100, 200);
|
||||
PandaTest test(can_list_size, cereal::PandaState::PandaType::DOS);
|
||||
void test_can_protocol() {
|
||||
for (auto hw_type : {cereal::PandaState::PandaType::DOS, cereal::PandaState::PandaType::RED_PANDA}) {
|
||||
for (int can_list_size : {1, 3, 5, 10, 30, 60, 100, 200}) {
|
||||
PandaTest send_test(can_list_size, hw_type);
|
||||
send_test.test_can_send();
|
||||
|
||||
SECTION("can_send") {
|
||||
test.test_can_send();
|
||||
}
|
||||
SECTION("can_receive") {
|
||||
test.test_can_recv();
|
||||
}
|
||||
SECTION("chunked_can_receive") {
|
||||
test.test_can_recv(0x40);
|
||||
PandaTest receive_test(can_list_size, hw_type);
|
||||
receive_test.test_can_recv();
|
||||
|
||||
PandaTest chunked_receive_test(can_list_size, hw_type);
|
||||
chunked_receive_test.test_can_recv(0x40);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("send/recv CAN FD packets") {
|
||||
auto can_list_size = GENERATE(1, 3, 5, 10, 30, 60, 100, 200);
|
||||
PandaTest test(can_list_size, cereal::PandaState::PandaType::RED_PANDA);
|
||||
|
||||
SECTION("can_send") {
|
||||
test.test_can_send();
|
||||
}
|
||||
SECTION("can_receive") {
|
||||
test.test_can_recv();
|
||||
}
|
||||
SECTION("chunked_can_receive") {
|
||||
test.test_can_recv(0x40);
|
||||
}
|
||||
int main() {
|
||||
return run_native_test(test_can_protocol);
|
||||
}
|
||||
|
||||
@@ -6,6 +6,3 @@ if arch != "Darwin":
|
||||
camera_obj = env.Object(['cameras/camera_qcom2.cc', 'cameras/camera_common.cc', 'cameras/spectra.cc',
|
||||
'cameras/cdm.cc', 'sensors/ox03c10.cc', 'sensors/os04c10.cc'])
|
||||
env.Program('camerad', ['main.cc', camera_obj], LIBS=libs)
|
||||
|
||||
if GetOption("extras") and arch == "x86_64":
|
||||
env.Program('test/test_ae_gray', ['test/test_ae_gray.cc', camera_obj], LIBS=libs)
|
||||
|
||||
@@ -1,84 +0,0 @@
|
||||
#define CATCH_CONFIG_MAIN
|
||||
#include "catch2/catch.hpp"
|
||||
|
||||
#include <cassert>
|
||||
|
||||
#include <cmath>
|
||||
#include <cstring>
|
||||
|
||||
#include "common/util.h"
|
||||
#include "system/camerad/cameras/camera_common.h"
|
||||
|
||||
#define W 240
|
||||
#define H 160
|
||||
|
||||
|
||||
#define TONE_SPLITS 3
|
||||
|
||||
float gts[TONE_SPLITS * TONE_SPLITS * TONE_SPLITS * TONE_SPLITS] = {
|
||||
0.917969, 0.917969, 0.375000, 0.917969, 0.375000, 0.375000, 0.187500, 0.187500, 0.187500, 0.917969,
|
||||
0.375000, 0.375000, 0.187500, 0.187500, 0.187500, 0.187500, 0.187500, 0.187500, 0.093750, 0.093750,
|
||||
0.093750, 0.093750, 0.093750, 0.093750, 0.093750, 0.093750, 0.093750, 0.917969, 0.375000, 0.375000,
|
||||
0.187500, 0.187500, 0.187500, 0.187500, 0.187500, 0.187500, 0.093750, 0.093750, 0.093750, 0.093750,
|
||||
0.093750, 0.093750, 0.093750, 0.093750, 0.093750, 0.093750, 0.093750, 0.093750, 0.093750, 0.093750,
|
||||
0.093750, 0.093750, 0.093750, 0.093750, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000,
|
||||
0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000,
|
||||
0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000,
|
||||
0.000000};
|
||||
|
||||
|
||||
TEST_CASE("camera.test_calculate_exposure_value") {
|
||||
// set up fake camerabuf
|
||||
CameraBuf cb = {};
|
||||
VisionBuf vb = {};
|
||||
uint8_t * fb_y = new uint8_t[W*H];
|
||||
vb.y = fb_y;
|
||||
cb.cur_yuv_buf = &vb;
|
||||
cb.out_img_width = W;
|
||||
cb.out_img_height = H;
|
||||
Rect rect = {0, 0, W-1, H-1};
|
||||
|
||||
printf("AE test patterns %dx%d\n", cb.out_img_width, cb.out_img_height);
|
||||
|
||||
// mix of 5 tones
|
||||
uint8_t l[5] = {0, 24, 48, 96, 235}; // 235 is yuv max
|
||||
|
||||
bool passed = true;
|
||||
float rtol = 0.05;
|
||||
// generate pattern and calculate EV
|
||||
int cnt = 0;
|
||||
for (int i_0=0; i_0<TONE_SPLITS; i_0++) {
|
||||
for (int i_1=0; i_1<TONE_SPLITS; i_1++) {
|
||||
for (int i_2=0; i_2<TONE_SPLITS; i_2++) {
|
||||
for (int i_3=0; i_3<TONE_SPLITS; i_3++) {
|
||||
int h_0 = i_0 * H / TONE_SPLITS;
|
||||
int h_1 = i_1 * (H - h_0) / TONE_SPLITS;
|
||||
int h_2 = i_2 * (H - h_0 - h_1) / TONE_SPLITS;
|
||||
int h_3 = i_3 * (H - h_0 - h_1 - h_2) / TONE_SPLITS;
|
||||
int h_4 = H - h_0 - h_1 - h_2 - h_3;
|
||||
memset(&fb_y[0], l[0], h_0*W);
|
||||
memset(&fb_y[h_0*W], l[1], h_1*W);
|
||||
memset(&fb_y[h_0*W+h_1*W], l[2], h_2*W);
|
||||
memset(&fb_y[h_0*W+h_1*W+h_2*W], l[3], h_3*W);
|
||||
memset(&fb_y[h_0*W+h_1*W+h_2*W+h_3*W], l[4], h_4*W);
|
||||
float ev = calculate_exposure_value((const CameraBuf*) &cb, rect, 1, 1);
|
||||
// printf("%d/%d/%d/%d/%d ev is %f\n", h_0, h_1, h_2, h_3, h_4, ev);
|
||||
// printf("%f\n", ev);
|
||||
|
||||
// compare to gt
|
||||
float evgt = gts[cnt];
|
||||
if (fabs(ev - evgt) > rtol*evgt) {
|
||||
passed = false;
|
||||
}
|
||||
|
||||
// report
|
||||
printf("%d/%d/%d/%d/%d: ev %f, gt %f, err %f\n", h_0, h_1, h_2, h_3, h_4, ev, evgt, fabs(ev - evgt) / (evgt != 0 ? evgt : 0.00001f));
|
||||
cnt++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
assert(passed);
|
||||
|
||||
delete[] fb_y;
|
||||
}
|
||||
@@ -17,6 +17,3 @@ libs.insert(0, logger_lib)
|
||||
env.Program('loggerd', ['loggerd.cc'], LIBS=libs, FRAMEWORKS=frameworks)
|
||||
env.Program('encoderd', ['encoderd.cc'], LIBS=libs, FRAMEWORKS=frameworks)
|
||||
env.Program('bootlog.cc', LIBS=libs, FRAMEWORKS=frameworks)
|
||||
|
||||
if GetOption('extras'):
|
||||
env.Program('tests/test_logger', ['tests/test_runner.cc', 'tests/test_logger.cc', 'tests/test_zstd_writer.cc'], LIBS=libs)
|
||||
|
||||
@@ -1,75 +0,0 @@
|
||||
#include "catch2/catch.hpp"
|
||||
#include "system/loggerd/logger.h"
|
||||
|
||||
typedef cereal::Sentinel::SentinelType SentinelType;
|
||||
|
||||
void verify_segment(const std::string &route_path, int segment, int max_segment, int required_event_cnt) {
|
||||
const std::string segment_path = route_path + "--" + std::to_string(segment);
|
||||
SentinelType begin_sentinel = segment == 0 ? SentinelType::START_OF_ROUTE : SentinelType::START_OF_SEGMENT;
|
||||
SentinelType end_sentinel = segment == max_segment - 1 ? SentinelType::END_OF_ROUTE : SentinelType::END_OF_SEGMENT;
|
||||
|
||||
REQUIRE(!util::file_exists(segment_path + "/rlog.lock"));
|
||||
for (const char *fn : {"/rlog.zst", "/qlog.zst"}) {
|
||||
const std::string log_file = segment_path + fn;
|
||||
std::string log = util::read_file(log_file);
|
||||
REQUIRE(!log.empty());
|
||||
std::string decompressed_log = zstd_decompress(log);
|
||||
int event_cnt = 0, i = 0;
|
||||
kj::ArrayPtr<const capnp::word> words((capnp::word *)decompressed_log.data(), decompressed_log.size() / sizeof(capnp::word));
|
||||
while (words.size() > 0) {
|
||||
try {
|
||||
capnp::FlatArrayMessageReader reader(words);
|
||||
auto event = reader.getRoot<cereal::Event>();
|
||||
words = kj::arrayPtr(reader.getEnd(), words.end());
|
||||
if (i == 0) {
|
||||
REQUIRE(event.which() == cereal::Event::INIT_DATA);
|
||||
} else if (i == 1) {
|
||||
REQUIRE(event.which() == cereal::Event::SENTINEL);
|
||||
REQUIRE(event.getSentinel().getType() == begin_sentinel);
|
||||
REQUIRE(event.getSentinel().getSignal() == 0);
|
||||
} else if (words.size() > 0) {
|
||||
REQUIRE(event.which() == cereal::Event::CLOCKS);
|
||||
++event_cnt;
|
||||
} else {
|
||||
// the last event must be SENTINEL
|
||||
REQUIRE(event.which() == cereal::Event::SENTINEL);
|
||||
REQUIRE(event.getSentinel().getType() == end_sentinel);
|
||||
REQUIRE(event.getSentinel().getSignal() == (end_sentinel == SentinelType::END_OF_ROUTE ? 1 : 0));
|
||||
}
|
||||
++i;
|
||||
} catch (const kj::Exception &ex) {
|
||||
INFO("failed parse " << i << " exception :" << ex.getDescription());
|
||||
REQUIRE(0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
REQUIRE(event_cnt == required_event_cnt);
|
||||
}
|
||||
}
|
||||
|
||||
void write_msg(LoggerState *logger) {
|
||||
MessageBuilder msg;
|
||||
msg.initEvent().initClocks();
|
||||
logger->write(msg.toBytes(), true);
|
||||
}
|
||||
|
||||
TEST_CASE("logger") {
|
||||
const int segment_cnt = 100;
|
||||
const std::string log_root = "/tmp/test_logger";
|
||||
REQUIRE(system(("rm " + log_root + " -rf").c_str()) == 0);
|
||||
std::string route_name;
|
||||
{
|
||||
LoggerState logger(log_root);
|
||||
route_name = logger.routeName();
|
||||
for (int i = 0; i < segment_cnt; ++i) {
|
||||
REQUIRE(logger.next());
|
||||
REQUIRE(util::file_exists(logger.segmentPath() + "/rlog.lock"));
|
||||
REQUIRE(logger.segment() == i);
|
||||
write_msg(&logger);
|
||||
}
|
||||
logger.setExitSignal(1);
|
||||
}
|
||||
for (int i = 0; i < segment_cnt; ++i) {
|
||||
verify_segment(log_root + "/" + route_name, i, segment_cnt, 1);
|
||||
}
|
||||
}
|
||||
@@ -1,2 +0,0 @@
|
||||
#define CATCH_CONFIG_MAIN
|
||||
#include "catch2/catch.hpp"
|
||||
@@ -1,44 +0,0 @@
|
||||
#include <zstd.h>
|
||||
|
||||
#include <catch2/catch.hpp>
|
||||
#include <cstring>
|
||||
#include <vector>
|
||||
|
||||
#include "common/util.h"
|
||||
#include "system/loggerd/logger.h"
|
||||
#include "system/loggerd/zstd_writer.h"
|
||||
|
||||
TEST_CASE("ZstdFileWriter writes and compresses data correctly in loops", "[ZstdFileWriter]") {
|
||||
const std::string filename = "test_zstd_file.zst";
|
||||
const int iterations = 100;
|
||||
const size_t dataSize = 1024;
|
||||
|
||||
std::string totalTestData;
|
||||
|
||||
// Step 1: Write compressed data to file in a loop
|
||||
{
|
||||
ZstdFileWriter writer(filename, LOG_COMPRESSION_LEVEL);
|
||||
// Write various data sizes including edge cases
|
||||
std::vector<size_t> testSizes = {dataSize, 1, 0, dataSize * 2}; // Normal, minimal, empty, large
|
||||
for (int i = 0; i < iterations; ++i) {
|
||||
size_t currentSize = testSizes[i % testSizes.size()];
|
||||
std::string testData = util::random_string(currentSize);
|
||||
totalTestData.append(testData);
|
||||
|
||||
writer.write((void *)testData.c_str(), testData.size());
|
||||
}
|
||||
}
|
||||
|
||||
// Step 2: Decompress the file and verify the data
|
||||
auto compressedContent = util::read_file(filename);
|
||||
REQUIRE(compressedContent.size() > 0);
|
||||
REQUIRE(compressedContent.size() < totalTestData.size());
|
||||
std::string decompressedData = zstd_decompress(compressedContent);
|
||||
|
||||
// Step 3: Verify that the decompressed data matches the original accumulated data
|
||||
REQUIRE(decompressedData.size() == totalTestData.size());
|
||||
REQUIRE(std::memcmp(decompressedData.data(), totalTestData.c_str(), totalTestData.size()) == 0);
|
||||
|
||||
// Clean up the test file
|
||||
std::remove(filename.c_str());
|
||||
}
|
||||
@@ -7,12 +7,9 @@ from openpilot.common.test import OpenpilotTestCase
|
||||
|
||||
|
||||
NATIVE_TESTS = (
|
||||
"openpilot/common/tests/test_common",
|
||||
"openpilot/common/tests/test_swaglog",
|
||||
"openpilot/selfdrive/pandad/tests/test_pandad_canprotocol",
|
||||
"openpilot/system/loggerd/tests/test_logger",
|
||||
"openpilot/tools/cabana/tests/test_cabana",
|
||||
"openpilot/tools/cabana/tests/test_dbc_core",
|
||||
"openpilot/tools/replay/tests/test_replay",
|
||||
)
|
||||
|
||||
|
||||
|
||||
@@ -110,14 +110,11 @@ cabana_lib = cabana_env.Library("cabana_lib", cabana_srcs + [bootstrap_icons_src
|
||||
cabana_env.Program('_cabana', ['cabana.cc', cabana_lib, assets], LIBS=cabana_libs, FRAMEWORKS=base_frameworks)
|
||||
|
||||
if GetOption('extras'):
|
||||
cabana_env.Program('tests/test_cabana', ['tests/test_runner.cc', 'tests/test_cabana.cc', cabana_lib], LIBS=[cabana_libs])
|
||||
|
||||
# This target deliberately uses the base environment and links no Qt libraries.
|
||||
# It prevents Qt dependencies from creeping back into the DBC core.
|
||||
dbc_core_test_env = env.Clone()
|
||||
dbc_core_test_env['CXXFLAGS'] += [opendbc_path]
|
||||
dbc_core_test_objects = [
|
||||
dbc_core_test_env.Object('tests/dbc_core_test_runner', 'tests/test_runner.cc'),
|
||||
dbc_core_test_env.Object('tests/dbc_core_tests', 'tests/test_cabana.cc'),
|
||||
dbc_core_test_env.Object('tests/dbc_core_model', 'dbc/dbc.cc'),
|
||||
dbc_core_test_env.Object('tests/dbc_core_file', 'dbc/dbcfile.cc'),
|
||||
|
||||
@@ -1,20 +1,14 @@
|
||||
|
||||
#undef INFO
|
||||
#include <filesystem>
|
||||
#include <sstream>
|
||||
|
||||
#include "catch2/catch.hpp"
|
||||
#include "common/tests/native_test.h"
|
||||
#include "tools/cabana/dbc/dbcfile.h"
|
||||
#include "tools/cabana/dbc/dbcmanager.h"
|
||||
#include "tools/cabana/core/settings.h"
|
||||
|
||||
#ifdef QT_CORE_LIB
|
||||
#include <QColor>
|
||||
#endif
|
||||
|
||||
const std::string TEST_RLOG_URL = "https://commadataci.blob.core.windows.net/openpilotci/0c94aa1e1296d7c6/2021-05-05--19-48-37/0/rlog.bz2";
|
||||
|
||||
TEST_CASE("DBCFile::generateDBC") {
|
||||
void test_generate_dbc() {
|
||||
std::string fn = std::string(OPENDBC_FILE_PATH) + "/tesla_can.dbc";
|
||||
DBCFile dbc_origin(fn);
|
||||
DBCFile dbc_from_generated("", dbc_origin.generateDBC());
|
||||
@@ -35,7 +29,7 @@ TEST_CASE("DBCFile::generateDBC") {
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("DBCFile::generateDBC - comment order") {
|
||||
void test_comment_order() {
|
||||
// Ensure that message comments are followed by signal comments and in the correct order
|
||||
std::string content = R"(BO_ 160 message_1: 8 EON
|
||||
SG_ signal_1 : 0|12@1+ (1,0) [0|4095] "unit" XXX
|
||||
@@ -52,7 +46,7 @@ CM_ SG_ 162 signal_2 "signal comment";
|
||||
REQUIRE(dbc.generateDBC() == content);
|
||||
}
|
||||
|
||||
TEST_CASE("DBCFile::generateDBC -- preserve original header") {
|
||||
void test_preserve_original_header() {
|
||||
std::string content = R"(VERSION "1.0"
|
||||
|
||||
NS_ :
|
||||
@@ -72,7 +66,7 @@ CM_ SG_ 160 signal_1 "signal comment";
|
||||
REQUIRE(dbc.generateDBC() == content);
|
||||
}
|
||||
|
||||
TEST_CASE("DBCFile::generateDBC - escaped quotes") {
|
||||
void test_escaped_quotes() {
|
||||
std::string content = R"(BO_ 160 message_1: 8 EON
|
||||
SG_ signal_1 : 0|12@1+ (1,0) [0|4095] "unit" XXX
|
||||
|
||||
@@ -83,7 +77,7 @@ CM_ SG_ 160 signal_1 "signal comment with \"escaped quotes\"";
|
||||
REQUIRE(dbc.generateDBC() == content);
|
||||
}
|
||||
|
||||
TEST_CASE("parse_dbc") {
|
||||
void test_parse_dbc() {
|
||||
std::string content = R"(
|
||||
BO_ 160 message_1: 8 EON
|
||||
SG_ signal_1 : 0|12@1+ (1,0) [0|4095] "unit" XXX
|
||||
@@ -149,7 +143,7 @@ CM_ SG_ 162 signal_1 "signal comment with \"escaped quotes\"";
|
||||
REQUIRE(msg->sigs[0]->comment == "signal comment with \"escaped quotes\"");
|
||||
}
|
||||
|
||||
TEST_CASE("parse_opendbc") {
|
||||
void test_parse_opendbc() {
|
||||
std::vector<std::string> errors;
|
||||
for (const auto &entry : std::filesystem::directory_iterator(OPENDBC_FILE_PATH)) {
|
||||
if (!entry.is_regular_file() || entry.path().extension() != ".dbc") continue;
|
||||
@@ -161,11 +155,11 @@ TEST_CASE("parse_opendbc") {
|
||||
}
|
||||
std::ostringstream details;
|
||||
for (const auto &error : errors) details << error << '\n';
|
||||
INFO(details.str());
|
||||
if (!errors.empty()) std::cerr << details.str();
|
||||
REQUIRE(errors.empty());
|
||||
}
|
||||
|
||||
TEST_CASE("DBCManager core callbacks") {
|
||||
void test_dbc_manager() {
|
||||
DBCManager manager;
|
||||
int files_changed = 0;
|
||||
int signals_added = 0;
|
||||
@@ -192,34 +186,16 @@ TEST_CASE("DBCManager core callbacks") {
|
||||
REQUIRE(manager.msg({.source = 0, .address = 160})->sig("speed") != nullptr);
|
||||
}
|
||||
|
||||
TEST_CASE("Cabana settings core defaults") {
|
||||
CabanaSettingsState state;
|
||||
REQUIRE(state.fps == 10);
|
||||
REQUIRE(state.chart_range == 180);
|
||||
REQUIRE(state.drag_direction == CabanaSettingsState::MsbFirst);
|
||||
REQUIRE(state.recent_files.empty());
|
||||
void test_cabana_core() {
|
||||
test_generate_dbc();
|
||||
test_comment_order();
|
||||
test_preserve_original_header();
|
||||
test_escaped_quotes();
|
||||
test_parse_dbc();
|
||||
test_parse_opendbc();
|
||||
test_dbc_manager();
|
||||
}
|
||||
|
||||
#ifdef QT_CORE_LIB
|
||||
TEST_CASE("CabanaColor preserves QColor transformations") {
|
||||
const std::vector<QColor> colors = {
|
||||
QColor(102, 86, 169, 64), QColor(0, 187, 255, 128), QColor(255, 0, 0, 128), QColor(45, 120, 75, 255),
|
||||
};
|
||||
for (const auto &qt_color : colors) {
|
||||
CabanaColor color(qt_color.red(), qt_color.green(), qt_color.blue(), qt_color.alpha());
|
||||
for (int factor : {75, 100, 135, 150, 200}) {
|
||||
const auto lighter = color.lighter(factor);
|
||||
const auto qt_lighter = qt_color.lighter(factor);
|
||||
CHECK(std::abs(lighter.red() - qt_lighter.red()) <= 1);
|
||||
CHECK(std::abs(lighter.green() - qt_lighter.green()) <= 1);
|
||||
CHECK(std::abs(lighter.blue() - qt_lighter.blue()) <= 1);
|
||||
|
||||
const auto darker = color.darker(factor);
|
||||
const auto qt_darker = qt_color.darker(factor);
|
||||
CHECK(std::abs(darker.red() - qt_darker.red()) <= 1);
|
||||
CHECK(std::abs(darker.green() - qt_darker.green()) <= 1);
|
||||
CHECK(std::abs(darker.blue() - qt_darker.blue()) <= 1);
|
||||
}
|
||||
}
|
||||
int main() {
|
||||
return run_native_test(test_cabana_core);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
#define CATCH_CONFIG_RUNNER
|
||||
#include "catch2/catch.hpp"
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
const int res = Catch::Session().run(argc, argv);
|
||||
return (res < 0xff ? res : 0xff);
|
||||
}
|
||||
@@ -14,6 +14,3 @@ replay_lib = replay_env.Library("replay", replay_lib_src, LIBS=base_libs, FRAMEW
|
||||
Export('replay_lib')
|
||||
replay_libs = [replay_lib] + ffmpeg_libs + ['bz2', 'zstd', 'ncurses'] + base_libs
|
||||
replay_env.Program("replay", ["main.cc"], LIBS=replay_libs, FRAMEWORKS=base_frameworks)
|
||||
|
||||
if GetOption('extras'):
|
||||
replay_env.Program('tests/test_replay', ['tests/test_replay.cc'], LIBS=replay_libs)
|
||||
|
||||
@@ -1,18 +0,0 @@
|
||||
#define CATCH_CONFIG_MAIN
|
||||
#include "catch2/catch.hpp"
|
||||
#include "tools/replay/filereader.h"
|
||||
#include "tools/replay/replay.h"
|
||||
|
||||
const std::string TEST_RLOG_URL = "https://commadataci.blob.core.windows.net/openpilotci/0c94aa1e1296d7c6/2021-05-05--19-48-37/0/rlog.bz2";
|
||||
|
||||
TEST_CASE("LogReader") {
|
||||
SECTION("corrupt log") {
|
||||
FileReader reader(true);
|
||||
std::string corrupt_content = reader.read(TEST_RLOG_URL);
|
||||
corrupt_content.resize(corrupt_content.length() / 2);
|
||||
corrupt_content = decompressBZ2(corrupt_content);
|
||||
LogReader log;
|
||||
REQUIRE(log.load(corrupt_content.data(), corrupt_content.size()));
|
||||
REQUIRE(log.events.size() > 0);
|
||||
}
|
||||
}
|
||||
@@ -22,7 +22,6 @@ dependencies = [
|
||||
|
||||
# vendored native dependencies
|
||||
"comma-deps-capnproto",
|
||||
"comma-deps-catch2",
|
||||
"comma-deps-acados",
|
||||
"comma-deps-ffmpeg",
|
||||
"comma-deps-zstd",
|
||||
|
||||
@@ -142,14 +142,6 @@ wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/80/a9/f61fe62045c4ea867f51f2d74b4edfabd6c272c62a3281a9f1f33825a725/comma_deps_capnproto-1.0.1.post93-py3-none-manylinux_2_28_x86_64.whl", hash = "sha256:f98cdba8f8c7f08a7a0c0a4b7cc0bfcf515e29ad8f1b5cb8eda4e253bef5e6e3", size = 2590769, upload-time = "2026-07-08T19:30:49.728Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "comma-deps-catch2"
|
||||
version = "2.13.10.post93"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/88/ee/b4ef7758d04a024775d49558ca930fec19aa37cd691ad9182b7141f4d4d7/comma_deps_catch2-2.13.10.post93-py3-none-any.whl", hash = "sha256:8f23293251b5db48c08885d8816ca252b3fb11b0c1c26775bae36e8b217e865e", size = 137085, upload-time = "2026-07-08T19:30:53.44Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "comma-deps-eigen"
|
||||
version = "3.4.0.post93"
|
||||
@@ -621,7 +613,6 @@ source = { editable = "msgq_repo" }
|
||||
|
||||
[package.metadata]
|
||||
requires-dist = [
|
||||
{ name = "catch2", marker = "extra == 'dev'", git = "https://github.com/commaai/dependencies.git?subdirectory=catch2&rev=release-catch2" },
|
||||
{ name = "codespell", marker = "extra == 'dev'" },
|
||||
{ name = "cppcheck", marker = "extra == 'dev'" },
|
||||
{ name = "cpplint", marker = "extra == 'dev'" },
|
||||
@@ -699,10 +690,8 @@ name = "openpilot"
|
||||
version = "0.1.0"
|
||||
source = { editable = "." }
|
||||
dependencies = [
|
||||
{ name = "cffi" },
|
||||
{ name = "comma-deps-acados" },
|
||||
{ name = "comma-deps-capnproto" },
|
||||
{ name = "comma-deps-catch2" },
|
||||
{ name = "comma-deps-ffmpeg" },
|
||||
{ name = "comma-deps-gcc-arm-none-eabi" },
|
||||
{ name = "comma-deps-git-lfs" },
|
||||
@@ -768,13 +757,11 @@ standalone = [
|
||||
|
||||
[package.metadata]
|
||||
requires-dist = [
|
||||
{ name = "cffi" },
|
||||
{ name = "codespell", marker = "extra == 'testing'" },
|
||||
{ name = "comma-deps-acados" },
|
||||
{ name = "comma-deps-bootstrap-icons", marker = "extra == 'tools'" },
|
||||
{ name = "comma-deps-bzip2", marker = "extra == 'tools'" },
|
||||
{ name = "comma-deps-capnproto" },
|
||||
{ name = "comma-deps-catch2" },
|
||||
{ name = "comma-deps-ffmpeg" },
|
||||
{ name = "comma-deps-gcc-arm-none-eabi" },
|
||||
{ name = "comma-deps-git-lfs" },
|
||||
|
||||
Reference in New Issue
Block a user