Skip to content

Commit 03859a2

Browse files
committed
Added tests for mixed C and C++ code
Also added delete_c_struct function, which is needed as the struct FdpDataPipeline is an incomplete type.
1 parent 9a86e07 commit 03859a2

File tree

3 files changed

+87
-4
lines changed

3 files changed

+87
-4
lines changed

include/fdp/fdp.h

+6-1
Original file line numberDiff line numberDiff line change
@@ -186,12 +186,17 @@ DataPipeline::sptr from_c_struct(FdpDataPipeline *data_pipeline);
186186
*
187187
* If the pipeline is set up using the C++ method DataPipeline::construct, this may be
188188
* used to generate a C-compatible struct. Note that this uses 'new' to allocate the
189-
* returned pointer, so the user should 'delete` the pointer after use to avoid memory
189+
* returned pointer, so the user should 'delete_c_struct` after use to avoid memory
190190
* leaks. It is not recommended to mix usage of the C and C++ APIs for init and finalise
191191
* functions.
192192
*/
193193
FdpDataPipeline* to_c_struct(DataPipeline::sptr data_pipeline);
194194

195+
/**
196+
* @brief Function to clean up FdpDataPipeline created by to_c_struct
197+
*/
198+
void delete_c_struct(FdpDataPipeline *data_pipeline);
199+
195200
} // close namespace FairDataPipeline
196201

197202
#endif

src/fdp_c_api.cxx

+7-2
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,11 @@ FdpDataPipeline* FDP::to_c_struct(FDP::DataPipeline::sptr data_pipeline){
2828
return new FdpDataPipeline{data_pipeline};
2929
}
3030

31+
32+
void FDP::delete_c_struct(FdpDataPipeline *data_pipeline){
33+
delete data_pipeline;
34+
}
35+
3136
/**
3237
* @brief Utility method, calls exception-raising function and returns error codes
3338
*
@@ -116,7 +121,7 @@ FdpError fdp_init(
116121
std::string(script_file_path),
117122
token_str
118123
);
119-
*data_pipeline = to_c_struct(cpp_data_pipeline);
124+
*data_pipeline = FDP::to_c_struct(cpp_data_pipeline);
120125
return err;
121126
}
122127

@@ -129,7 +134,7 @@ FdpError fdp_finalise(FdpDataPipeline **data_pipeline){
129134
[](FDP::DataPipeline::sptr pipeline){pipeline->finalise();},
130135
(*data_pipeline)->_pipeline
131136
);
132-
delete *data_pipeline;
137+
FDP::delete_c_struct(*data_pipeline);
133138
*data_pipeline = nullptr;
134139
return err;
135140
}

test/test_c_api.cxx

+74-1
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ std::string home_dir(){
3131

3232
TEST(CTest, link_read_write){
3333
fdp_set_log_level(FDP_LOG_DEBUG);
34+
char buf[512];
3435

3536
// Initialise
3637
FdpDataPipeline* pipeline;
@@ -48,7 +49,6 @@ TEST(CTest, link_read_write){
4849
),
4950
FDP_ERR_NONE
5051
);
51-
char buf[512];
5252

5353
// Test link write
5454
buf[0] = '\0'; // Ensure strlen of output buffer is 0
@@ -82,6 +82,79 @@ TEST(CTest, link_read_write){
8282
EXPECT_EQ(fdp_finalise(&pipeline), FDP_ERR_NONE);
8383
}
8484

85+
TEST(CTest, cpp_to_c){
86+
fdp_set_log_level(FDP_LOG_DEBUG);
87+
char buf[512];
88+
89+
// Initialise using C++
90+
fs::path config = fs::path(TESTDIR) / "data" / "write_csv.yaml";
91+
fs::path script = fs::path(TESTDIR) / "test_script.sh";
92+
std::string token = fdp::read_token(
93+
fs::path(home_dir()) / ".fair" / "registry" / "token"
94+
);
95+
auto cpp_pipeline = fdp::DataPipeline::construct(
96+
config.string(), script.string(), token
97+
);
98+
99+
// Switch to C API, use temporary FdpDataPipeline
100+
FdpDataPipeline *c_pipeline = fdp::to_c_struct(cpp_pipeline);
101+
102+
// Test link write
103+
buf[0] = '\0'; // Ensure strlen of output buffer is 0
104+
EXPECT_EQ(fdp_link_write(c_pipeline, "test/csv", buf), FDP_ERR_NONE);
105+
EXPECT_GT(strlen(buf), 1);
106+
107+
// Write to new path
108+
std::ofstream fstream(buf);
109+
fstream << "Test";
110+
fstream.close();
111+
112+
// Finish working in C, delete FdpDataPipeline
113+
fdp::delete_c_struct(c_pipeline);
114+
115+
// Finalise in C++
116+
cpp_pipeline->finalise();
117+
}
118+
119+
TEST(CTest, c_to_cpp){
120+
fdp_set_log_level(FDP_LOG_DEBUG);
121+
122+
// Initialise using C
123+
FdpDataPipeline* c_pipeline;
124+
fs::path config = fs::path(TESTDIR) / "data" / "write_csv.yaml";
125+
fs::path script = fs::path(TESTDIR) / "test_script.sh";
126+
std::string token = fdp::read_token(
127+
fs::path(home_dir()) / ".fair" / "registry" / "token"
128+
);
129+
ASSERT_EQ(
130+
fdp_init(
131+
&c_pipeline,
132+
config.string().c_str(),
133+
script.string().c_str(),
134+
token.c_str()
135+
),
136+
FDP_ERR_NONE
137+
);
138+
139+
// Switch to C++ API
140+
auto cpp_pipeline = fdp::from_c_struct(c_pipeline);
141+
142+
// Test link write
143+
std::string data_product = "test/csv";
144+
fs::path currentLink = fs::path(cpp_pipeline->link_write(data_product));
145+
EXPECT_GT(currentLink.string().size(), 1);
146+
147+
// Write to new path
148+
std::ofstream fstream(currentLink);
149+
fstream << "Test";
150+
fstream.close();
151+
152+
// Finish working in C++
153+
cpp_pipeline = nullptr;
154+
155+
// Finalise in C
156+
EXPECT_EQ(fdp_finalise(&c_pipeline), FDP_ERR_NONE);
157+
}
85158

86159
TEST(CTest, log_levels){
87160
fdp_set_log_level(FDP_LOG_INFO);

0 commit comments

Comments
 (0)