Skip to content

Commit 07b1bb6

Browse files
authored
Tests (#9)
1 parent 3d848c9 commit 07b1bb6

File tree

10 files changed

+972
-104
lines changed

10 files changed

+972
-104
lines changed

.github/workflows/ci.yaml

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
name: C++ CI
2+
3+
on:
4+
push:
5+
branches: [ main ]
6+
pull_request:
7+
branches: [ main ]
8+
9+
jobs:
10+
build-and-test:
11+
name: C++ - ${{ github.event_name }}
12+
runs-on: ubuntu-latest
13+
permissions:
14+
actions: write
15+
contents: read
16+
steps:
17+
# 1. Check out your code
18+
- uses: actions/checkout@v4
19+
# # 2. Install dependencies (if using vcpkg, Conan, etc.)
20+
# - name: Install dependencies
21+
# run: sudo apt update && sudo apt install -y cmake g++ make
22+
- run: cmake -S . -B build -DCMAKE_BUILD_TYPE=Release
23+
- run: cmake --build build --parallel
24+
- run: ctest --test-dir build --output-on-failure --verbose --no-compress-output

CMakeLists.txt

Lines changed: 77 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -1,72 +1,91 @@
1-
cmake_minimum_required(VERSION 3.10)
1+
cmake_minimum_required(VERSION 3.16)
22
project(YAMLWrapper)
33

44
set(CMAKE_CXX_STANDARD 17)
55
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
66
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
77

8-
if(APPLE)
9-
# Check for package managers
10-
execute_process(COMMAND which brew OUTPUT_VARIABLE HOMEBREW_EXISTS OUTPUT_STRIP_TRAILING_WHITESPACE)
11-
execute_process(COMMAND which port OUTPUT_VARIABLE MACPORTS_EXISTS OUTPUT_STRIP_TRAILING_WHITESPACE)
12-
execute_process(COMMAND which conda OUTPUT_VARIABLE CONDA_EXISTS OUTPUT_STRIP_TRAILING_WHITESPACE)
8+
enable_testing()
9+
include(FetchContent)
10+
11+
FetchContent_Declare(
12+
yaml-cpp
13+
GIT_REPOSITORY https://github.com/jbeder/yaml-cpp.git
14+
GIT_TAG 0.8.0
15+
)
16+
FetchContent_Declare(
17+
Catch2
18+
GIT_REPOSITORY https://github.com/catchorg/Catch2.git
19+
GIT_TAG v3.5.2
20+
)
21+
22+
FetchContent_MakeAvailable(yaml-cpp)
23+
FetchContent_MakeAvailable(Catch2)
24+
add_subdirectory(tests)
25+
26+
file(COPY ${CMAKE_SOURCE_DIR}/lattice_files/
27+
DESTINATION ${CMAKE_BINARY_DIR}/lattice_files/)
28+
29+
# if(APPLE)
30+
# # Check for package managers
31+
# execute_process(COMMAND which brew OUTPUT_VARIABLE HOMEBREW_EXISTS OUTPUT_STRIP_TRAILING_WHITESPACE)
32+
# execute_process(COMMAND which port OUTPUT_VARIABLE MACPORTS_EXISTS OUTPUT_STRIP_TRAILING_WHITESPACE)
33+
# execute_process(COMMAND which conda OUTPUT_VARIABLE CONDA_EXISTS OUTPUT_STRIP_TRAILING_WHITESPACE)
1334

14-
# Error if both Homebrew and MacPorts exist
15-
if(HOMEBREW_EXISTS AND MACPORTS_EXISTS)
16-
message(FATAL_ERROR
17-
"Both Homebrew and MacPorts detected. This can cause conflicts.\n"
18-
"Please use only one package manager:\n"
19-
" - Homebrew found at: ${HOMEBREW_EXISTS}\n"
20-
" - MacPorts found at: ${MACPORTS_EXISTS}\n"
21-
"Consider uninstalling one to avoid library conflicts."
22-
)
23-
endif()
35+
# # Error if both Homebrew and MacPorts exist
36+
# if(HOMEBREW_EXISTS AND MACPORTS_EXISTS)
37+
# message(FATAL_ERROR
38+
# "Both Homebrew and MacPorts detected. This can cause conflicts.\n"
39+
# "Please use only one package manager:\n"
40+
# " - Homebrew found at: ${HOMEBREW_EXISTS}\n"
41+
# " - MacPorts found at: ${MACPORTS_EXISTS}\n"
42+
# "Consider uninstalling one to avoid library conflicts."
43+
# )
44+
# endif()
2445

25-
# Set RPATH based on which package manager is found
26-
set(BASE_RPATH "@executable_path/../lib;@loader_path")
46+
# # Set RPATH based on which package manager is found
47+
# set(BASE_RPATH "@executable_path/../lib;@loader_path")
2748

28-
if(HOMEBREW_EXISTS)
29-
message(STATUS "Using Homebrew package manager")
30-
# Check if Apple Silicon or Intel
31-
execute_process(
32-
COMMAND uname -m
33-
OUTPUT_VARIABLE ARCH
34-
OUTPUT_STRIP_TRAILING_WHITESPACE
35-
)
36-
if(ARCH STREQUAL "arm64")
37-
set(CMAKE_INSTALL_RPATH "${BASE_RPATH};/opt/homebrew/lib")
38-
list(APPEND CMAKE_PREFIX_PATH "/opt/homebrew")
39-
else()
40-
set(CMAKE_INSTALL_RPATH "${BASE_RPATH};/usr/local/lib")
41-
list(APPEND CMAKE_PREFIX_PATH "/usr/local")
42-
endif()
43-
elseif(MACPORTS_EXISTS)
44-
message(STATUS "Using MacPorts package manager")
45-
set(CMAKE_INSTALL_RPATH "${BASE_RPATH};/opt/local/lib")
46-
list(APPEND CMAKE_PREFIX_PATH "/opt/local")
47-
elseif(CONDA_EXISTS)
48-
message(STATUS "Using Conda package manager")
49-
# Get conda prefix
50-
execute_process(
51-
COMMAND conda info --base
52-
OUTPUT_VARIABLE CONDA_PREFIX
53-
OUTPUT_STRIP_TRAILING_WHITESPACE
54-
)
55-
set(CMAKE_INSTALL_RPATH "${BASE_RPATH};${CONDA_PREFIX}/lib")
56-
list(APPEND CMAKE_PREFIX_PATH "${CONDA_PREFIX}")
57-
else()
58-
message(STATUS "No package manager detected, using default paths")
59-
set(CMAKE_INSTALL_RPATH "${BASE_RPATH};/usr/local/lib")
60-
endif()
49+
# if(HOMEBREW_EXISTS)
50+
# message(STATUS "Using Homebrew package manager")
51+
# # Check if Apple Silicon or Intel
52+
# execute_process(
53+
# COMMAND uname -m
54+
# OUTPUT_VARIABLE ARCH
55+
# OUTPUT_STRIP_TRAILING_WHITESPACE
56+
# )
57+
# if(ARCH STREQUAL "arm64")
58+
# set(CMAKE_INSTALL_RPATH "${BASE_RPATH};/opt/homebrew/lib")
59+
# list(APPEND CMAKE_PREFIX_PATH "/opt/homebrew")
60+
# else()
61+
# set(CMAKE_INSTALL_RPATH "${BASE_RPATH};/usr/local/lib")
62+
# list(APPEND CMAKE_PREFIX_PATH "/usr/local")
63+
# endif()
64+
# elseif(MACPORTS_EXISTS)
65+
# message(STATUS "Using MacPorts package manager")
66+
# set(CMAKE_INSTALL_RPATH "${BASE_RPATH};/opt/local/lib")
67+
# list(APPEND CMAKE_PREFIX_PATH "/opt/local")
68+
# elseif(CONDA_EXISTS)
69+
# message(STATUS "Using Conda package manager")
70+
# # Get conda prefix
71+
# execute_process(
72+
# COMMAND conda info --base
73+
# OUTPUT_VARIABLE CONDA_PREFIX
74+
# OUTPUT_STRIP_TRAILING_WHITESPACE
75+
# )
76+
# set(CMAKE_INSTALL_RPATH "${BASE_RPATH};${CONDA_PREFIX}/lib")
77+
# list(APPEND CMAKE_PREFIX_PATH "${CONDA_PREFIX}")
78+
# else()
79+
# message(STATUS "No package manager detected, using default paths")
80+
# set(CMAKE_INSTALL_RPATH "${BASE_RPATH};/usr/local/lib")
81+
# endif()
6182

62-
set(CMAKE_BUILD_WITH_INSTALL_RPATH TRUE)
63-
message(STATUS "RPATH set to: ${CMAKE_INSTALL_RPATH}")
64-
endif()
65-
66-
find_package(yaml-cpp REQUIRED)
83+
# set(CMAKE_BUILD_WITH_INSTALL_RPATH TRUE)
84+
# message(STATUS "RPATH set to: ${CMAKE_INSTALL_RPATH}")
85+
# endif()
6786

6887
add_library(yaml_c_wrapper SHARED src/yaml_c_wrapper.cpp)
6988
target_link_libraries(yaml_c_wrapper yaml-cpp)
7089

71-
add_executable(yaml_reader src/yaml_reader.cpp)
72-
target_link_libraries(yaml_reader yaml_c_wrapper)
90+
add_executable(yaml_reader examples/yaml_reader.cpp)
91+
target_link_libraries(yaml_reader yaml_c_wrapper)

README.md

Lines changed: 27 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
## Introduction
22
yaml_c_wrapper.cpp wraps YAML::Node into C objects so they can be part of a shared object library to interface with other languages
3-
3+
<!--
44
First install yaml-cpp by running
55
66
macOS:
@@ -20,16 +20,31 @@ cd yaml-cpp/src
2020
mkdir build && cd build
2121
cmake ..
2222
cmake --build .
23-
cmake --install .
23+
cmake --install . -->
2424

25-
Next, in pals-cpp, run
25+
## Usage
26+
In pals-cpp, run
2627

27-
mkdir build && cd build
28-
cmake .. -DYAML_BUILD_SHARED_LIBS=ON
29-
make
30-
31-
## Example
32-
See yaml_reader.cpp for an example of how to use the library to read a lattice file,
33-
perform a basic manipulation, and write to another lattice file.
34-
Navigate to the build directly and run
35-
./yaml_reader
28+
cmake -DCMAKE_POLICY_VERSION_MINIMUM=3.5 -S . -B build
29+
cmake --build build
30+
31+
This builds libyaml_c_wrapper.dylib, a shared object library that can be used
32+
by other languages.
33+
34+
It also builds an executable using yaml_reader.cpp containing examples for how
35+
to use the library to read lattice files, perform basic manipulations, and write
36+
to other lattice files. To see the output, navigate to the build directory and run
37+
./yaml_reader
38+
39+
It will also build the tests.
40+
41+
## Testing
42+
In the root pals-cpp directory, run
43+
ctest --test-dir build --output-on-failure
44+
45+
To run a specific test, run
46+
ctest --test-dir build -R "Test Name"
47+
48+
## Issue
49+
yaml-cpp's cmake only requires cmake version 3.4, which is deprecated. Warnings must
50+
be suppressed to run properly

examples/yaml_reader.cpp

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
#include "../src/yaml_c_wrapper.h"
2+
#include <iostream>
3+
4+
int main() {
5+
// reading a lattice from a yaml file
6+
YAMLNodeHandle handle = yaml_parse_file("../lattice_files/ex.yaml");
7+
// printing to terminal
8+
std::cout << yaml_to_string(handle) << std::endl << std::endl;
9+
10+
// type checking
11+
std::cout << (yaml_is_sequence(handle)) << "\n";
12+
13+
// accessing sequence
14+
YAMLNodeHandle node = yaml_get_index(handle, 0);
15+
std::cout << "the first element is: \n" << yaml_to_string(node) << "\n";
16+
17+
// accessing map
18+
std::cout << "\nthe value at key 'thingB' is: " << yaml_to_string(yaml_get_key(node, "thingB")) << "\n";
19+
20+
// creating a new node that's a map
21+
YAMLNodeHandle map = yaml_create_map();
22+
yaml_set_int(map, "first", 1);
23+
24+
// creating a new node that's a sequence
25+
YAMLNodeHandle sequence = yaml_create_sequence();
26+
yaml_push_string(sequence, "magnet1");
27+
yaml_push_string(sequence, "");
28+
YAMLNodeHandle scalar = yaml_create_scalar();
29+
yaml_set_scalar_string(scalar, "magnet2");
30+
yaml_set_at_index(sequence, 1, scalar);
31+
32+
// adding new nodes to lattice
33+
yaml_push_node(handle, map);
34+
yaml_push_node(handle, sequence);
35+
36+
// writing modified lattice file to expand.yaml
37+
yaml_write_file(handle, "../lattice_files/expand.yaml");
38+
}

lattice_files/ex.yaml

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,5 +14,4 @@
1414
length: 1.03
1515
direction: -1
1616
- a_subline: # Item a_subline is repeated three times
17-
repeat: 3
18-
hi: 2
17+
repeat: 3

src/yaml_c_wrapper.cpp

Lines changed: 39 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -125,9 +125,6 @@ extern "C" {
125125
return static_cast<YAML::Node*>(handle)->size();
126126
}
127127

128-
// === ITERATION HELPERS ===
129-
130-
// For iterating over maps - get all keys
131128
char** yaml_get_keys(YAMLNodeHandle handle, int* out_count) {
132129
auto node = static_cast<YAML::Node*>(handle);
133130
if (!node->IsMap()) {
@@ -149,20 +146,6 @@ extern "C" {
149146
return result;
150147
}
151148

152-
void yaml_free_keys(char** keys, int count) {
153-
for (int i = 0; i < count; i++) {
154-
delete[] keys[i];
155-
}
156-
delete[] keys;
157-
}
158-
159-
// Set node at index for sequences
160-
void yaml_set_at_index(YAMLNodeHandle handle, int index, YAMLNodeHandle value) {
161-
auto node = static_cast<YAML::Node*>(handle);
162-
auto val_node = static_cast<YAML::Node*>(value);
163-
(*node)[index] = *val_node;
164-
}
165-
166149
// === CONVERT TO C TYPES (caller must free returned strings) ===
167150
char* yaml_as_string(YAMLNodeHandle handle) {
168151
try {
@@ -225,6 +208,37 @@ extern "C" {
225208
auto val_node = static_cast<YAML::Node*>(value);
226209
(*node)[key] = *val_node;
227210
}
211+
212+
void yaml_set_scalar_string(YAMLNodeHandle handle, const char* value) {
213+
if (handle == nullptr || value == nullptr) return;
214+
auto node = static_cast<YAML::Node*>(handle);
215+
*node = value;
216+
}
217+
218+
void yaml_set_scalar_int(YAMLNodeHandle handle, int value) {
219+
if (handle == nullptr) return;
220+
auto node = static_cast<YAML::Node*>(handle);
221+
*node = value;
222+
}
223+
224+
void yaml_set_scalar_float(YAMLNodeHandle handle, double value) {
225+
if (handle == nullptr) return;
226+
auto node = static_cast<YAML::Node*>(handle);
227+
*node = value;
228+
}
229+
230+
void yaml_set_scalar_bool(YAMLNodeHandle handle, bool value) {
231+
if (handle == nullptr) return;
232+
auto node = static_cast<YAML::Node*>(handle);
233+
*node = value;
234+
}
235+
236+
// Set node at index for sequences
237+
void yaml_set_at_index(YAMLNodeHandle handle, int index, YAMLNodeHandle value) {
238+
auto node = static_cast<YAML::Node*>(handle);
239+
auto val_node = static_cast<YAML::Node*>(value);
240+
(*node)[index] = *val_node;
241+
}
228242

229243
void yaml_push_string(YAMLNodeHandle handle, const char* value) {
230244
auto node = static_cast<YAML::Node*>(handle);
@@ -395,6 +409,14 @@ extern "C" {
395409
void yaml_free_string(char* str) {
396410
delete[] str;
397411
}
412+
413+
void yaml_free_keys(char** keys, int count) {
414+
for (int i = 0; i < count; i++) {
415+
delete[] keys[i];
416+
}
417+
delete[] keys;
418+
}
419+
398420

399421
YAMLNodeHandle yaml_clone(YAMLNodeHandle handle) {
400422
return new YAML::Node(YAML::Clone(*static_cast<YAML::Node*>(handle)));

src/yaml_c_wrapper.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ typedef void* YAMLNodeHandle;
1313
YAMLNodeHandle yaml_create_node(void);
1414
YAMLNodeHandle yaml_create_map(void);
1515
YAMLNodeHandle yaml_create_sequence(void);
16+
YAMLNodeHandle yaml_create_scalar();
1617
void yaml_delete_node(YAMLNodeHandle handle);
1718

1819
// === PARSING ===
@@ -24,7 +25,6 @@ bool yaml_is_scalar(YAMLNodeHandle handle);
2425
bool yaml_is_sequence(YAMLNodeHandle handle);
2526
bool yaml_is_map(YAMLNodeHandle handle);
2627
bool yaml_is_null(YAMLNodeHandle handle);
27-
bool yaml_is_defined(YAMLNodeHandle handle);
2828

2929
// === ACCESS ===
3030
YAMLNodeHandle yaml_get_key(YAMLNodeHandle handle, const char* key);
@@ -46,6 +46,12 @@ void yaml_set_float(YAMLNodeHandle handle, const char* key, double value);
4646
void yaml_set_bool(YAMLNodeHandle handle, const char* key, bool value);
4747
void yaml_set_node(YAMLNodeHandle handle, const char* key, YAMLNodeHandle value);
4848

49+
void yaml_set_scalar_string(YAMLNodeHandle handle, const char* value);
50+
void yaml_set_scalar_int(YAMLNodeHandle handle, int value);
51+
void yaml_set_scalar_float(YAMLNodeHandle handle, double value);
52+
void yaml_set_scalar_bool(YAMLNodeHandle handle, bool value);
53+
54+
void yaml_set_at_index(YAMLNodeHandle handle, int index, YAMLNodeHandle value) ;
4955
void yaml_push_string(YAMLNodeHandle handle, const char* value);
5056
void yaml_push_int(YAMLNodeHandle handle, int value);
5157
void yaml_push_float(YAMLNodeHandle handle, double value);

0 commit comments

Comments
 (0)