Build unit test for C with mocked dependencies using bazel
.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty{ height:90px;width:728px;box-sizing:border-box;
}
I have a C codebase I'm trying to build with Bazel. This codebase is covered with unit tests that use the fff library for generating function mocks in C. The actual library is not important though, I have a problem with the whole concept of function mocks.
Right now I have a makefile where I link and run my tests. When I build a test, I compile and link the library under test and the test source itself. This test also defines mocks for library's dependencies. When linked, mocked symbols get resolved to mock implementations and everything's working as expected. But the reason it does so is that I don't link the actual dependency library, I only link the mock symbols defined in the test source.
The main question is: how do I do this with Bazel? When linking the binary for a cc_test
target, Bazel compilis and links all transitive dependencies. Since the library under test depends (via deps
) on the real implementation of a symbol, this real definition is linked alongside the mock one and naturally I get this error: multiple definition of XXX
.
Example:
cc_library(
name = "a",
# a.cc has the real version of "void some_function()".
srcs = ["a.cc"],
hdrs = ["a.h"],
)
# This test is working just fine.
cc_test(
name = "a_test",
srcs = ["a_test.cpp"],
deps = [":a"],
)
cc_library(
name = "b",
# b.cc includes a.h and uses "void some_function()".
srcs = ["b.cc"],
hdrs = ["b.h"],
deps = [":a"],
)
# This test has two definitions for "void some_function()":
# the real one and the mock one.
cc_test(
name = "b_test",
# b_test.cpp has the mock version of "void some_function()".
srcs = ["b_test.cpp"],
deps = [":b"],
)
I'm not exactly new to Bazel, but I'm not an expert either and after spending many hours trying things I have failed. Any advice on how do I make it work?
c bazel
add a comment |
I have a C codebase I'm trying to build with Bazel. This codebase is covered with unit tests that use the fff library for generating function mocks in C. The actual library is not important though, I have a problem with the whole concept of function mocks.
Right now I have a makefile where I link and run my tests. When I build a test, I compile and link the library under test and the test source itself. This test also defines mocks for library's dependencies. When linked, mocked symbols get resolved to mock implementations and everything's working as expected. But the reason it does so is that I don't link the actual dependency library, I only link the mock symbols defined in the test source.
The main question is: how do I do this with Bazel? When linking the binary for a cc_test
target, Bazel compilis and links all transitive dependencies. Since the library under test depends (via deps
) on the real implementation of a symbol, this real definition is linked alongside the mock one and naturally I get this error: multiple definition of XXX
.
Example:
cc_library(
name = "a",
# a.cc has the real version of "void some_function()".
srcs = ["a.cc"],
hdrs = ["a.h"],
)
# This test is working just fine.
cc_test(
name = "a_test",
srcs = ["a_test.cpp"],
deps = [":a"],
)
cc_library(
name = "b",
# b.cc includes a.h and uses "void some_function()".
srcs = ["b.cc"],
hdrs = ["b.h"],
deps = [":a"],
)
# This test has two definitions for "void some_function()":
# the real one and the mock one.
cc_test(
name = "b_test",
# b_test.cpp has the mock version of "void some_function()".
srcs = ["b_test.cpp"],
deps = [":b"],
)
I'm not exactly new to Bazel, but I'm not an expert either and after spending many hours trying things I have failed. Any advice on how do I make it work?
c bazel
1
why do you tag c++ for a C question?
– phuclv
Jan 6 at 2:43
as far as I see the whole project is in c++ and not c. you use the suffix cpp and also the c++ connector of bazel (they don't have one for c I think). Don't know if usage of fff is possible then but that's another problem.
– David
Jan 9 at 23:07
add a comment |
I have a C codebase I'm trying to build with Bazel. This codebase is covered with unit tests that use the fff library for generating function mocks in C. The actual library is not important though, I have a problem with the whole concept of function mocks.
Right now I have a makefile where I link and run my tests. When I build a test, I compile and link the library under test and the test source itself. This test also defines mocks for library's dependencies. When linked, mocked symbols get resolved to mock implementations and everything's working as expected. But the reason it does so is that I don't link the actual dependency library, I only link the mock symbols defined in the test source.
The main question is: how do I do this with Bazel? When linking the binary for a cc_test
target, Bazel compilis and links all transitive dependencies. Since the library under test depends (via deps
) on the real implementation of a symbol, this real definition is linked alongside the mock one and naturally I get this error: multiple definition of XXX
.
Example:
cc_library(
name = "a",
# a.cc has the real version of "void some_function()".
srcs = ["a.cc"],
hdrs = ["a.h"],
)
# This test is working just fine.
cc_test(
name = "a_test",
srcs = ["a_test.cpp"],
deps = [":a"],
)
cc_library(
name = "b",
# b.cc includes a.h and uses "void some_function()".
srcs = ["b.cc"],
hdrs = ["b.h"],
deps = [":a"],
)
# This test has two definitions for "void some_function()":
# the real one and the mock one.
cc_test(
name = "b_test",
# b_test.cpp has the mock version of "void some_function()".
srcs = ["b_test.cpp"],
deps = [":b"],
)
I'm not exactly new to Bazel, but I'm not an expert either and after spending many hours trying things I have failed. Any advice on how do I make it work?
c bazel
I have a C codebase I'm trying to build with Bazel. This codebase is covered with unit tests that use the fff library for generating function mocks in C. The actual library is not important though, I have a problem with the whole concept of function mocks.
Right now I have a makefile where I link and run my tests. When I build a test, I compile and link the library under test and the test source itself. This test also defines mocks for library's dependencies. When linked, mocked symbols get resolved to mock implementations and everything's working as expected. But the reason it does so is that I don't link the actual dependency library, I only link the mock symbols defined in the test source.
The main question is: how do I do this with Bazel? When linking the binary for a cc_test
target, Bazel compilis and links all transitive dependencies. Since the library under test depends (via deps
) on the real implementation of a symbol, this real definition is linked alongside the mock one and naturally I get this error: multiple definition of XXX
.
Example:
cc_library(
name = "a",
# a.cc has the real version of "void some_function()".
srcs = ["a.cc"],
hdrs = ["a.h"],
)
# This test is working just fine.
cc_test(
name = "a_test",
srcs = ["a_test.cpp"],
deps = [":a"],
)
cc_library(
name = "b",
# b.cc includes a.h and uses "void some_function()".
srcs = ["b.cc"],
hdrs = ["b.h"],
deps = [":a"],
)
# This test has two definitions for "void some_function()":
# the real one and the mock one.
cc_test(
name = "b_test",
# b_test.cpp has the mock version of "void some_function()".
srcs = ["b_test.cpp"],
deps = [":b"],
)
I'm not exactly new to Bazel, but I'm not an expert either and after spending many hours trying things I have failed. Any advice on how do I make it work?
c bazel
c bazel
edited Jan 7 at 4:02
monnoroch
asked Dec 27 '18 at 20:20
monnorochmonnoroch
20019
20019
1
why do you tag c++ for a C question?
– phuclv
Jan 6 at 2:43
as far as I see the whole project is in c++ and not c. you use the suffix cpp and also the c++ connector of bazel (they don't have one for c I think). Don't know if usage of fff is possible then but that's another problem.
– David
Jan 9 at 23:07
add a comment |
1
why do you tag c++ for a C question?
– phuclv
Jan 6 at 2:43
as far as I see the whole project is in c++ and not c. you use the suffix cpp and also the c++ connector of bazel (they don't have one for c I think). Don't know if usage of fff is possible then but that's another problem.
– David
Jan 9 at 23:07
1
1
why do you tag c++ for a C question?
– phuclv
Jan 6 at 2:43
why do you tag c++ for a C question?
– phuclv
Jan 6 at 2:43
as far as I see the whole project is in c++ and not c. you use the suffix cpp and also the c++ connector of bazel (they don't have one for c I think). Don't know if usage of fff is possible then but that's another problem.
– David
Jan 9 at 23:07
as far as I see the whole project is in c++ and not c. you use the suffix cpp and also the c++ connector of bazel (they don't have one for c I think). Don't know if usage of fff is possible then but that's another problem.
– David
Jan 9 at 23:07
add a comment |
1 Answer
1
active
oldest
votes
Your problem is probably a very basic one, that is related to namespaces and/or extending classes.
c has no namespaces by definition but they can be emulated somehow:
https://stackoverflow.com/a/28535585/1019850
But as you probably use c++ and never c, namespaces could be used directly.
The concrete problem is that you've two times the same function which would be expressed with namespaces a.some_function()
and b.some_function()
.
In Bazel there exist several options how to solve it, I post just short copied snippets, details you've to read on the linked pages.
deps = [
"@gtest//:main",
"//lib:hello-greet",
],
Link: https://docs.bazel.build/versions/master/cpp-use-cases.html
There the snippet is used also for tests but I think that's not important related to your problem.
Then there exist toolchains in Bazel, here is an example:
config_setting(
name = "on_linux",
constraint_values = [
"@bazel_tools//platforms:linux",
],
)
config_setting(
name = "on_windows",
constraint_values = [
"@bazel_tools//platforms:windows",
],
)
bar_binary(
name = "myprog",
srcs = ["mysrc.bar"],
compiler = select({
":on_linux": "//bar_tools:barc_linux",
":on_windows": "//bar_tools:barc_windows",
}),
)
Link: https://docs.bazel.build/versions/master/toolchains.html
As I'm not programming in c or c++ usually it would take me quite some time to dig enough in it to post the solution, so I've to keep it without a real solution but I hope the problem and the way to solve it got a bit clearer.
I'd try it with the second link first, below the first snippet above.
Thanks, but this is not the problem I'm trying to solve. And yes, I do, in fact, use C, not C++. I do use C++ library GoogleTest for unit tests, but code under test is pure C. In any case, the question is about linking, not compiling.
– monnoroch
Jan 11 at 4:10
why you use cc and cpp file-suffix? your problem is related to these files. The recommended way in my answer never mentions compiling, but different ways how to link the 'deps'
– David
Jan 11 at 9:55
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53950443%2fbuild-unit-test-for-c-with-mocked-dependencies-using-bazel%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
Your problem is probably a very basic one, that is related to namespaces and/or extending classes.
c has no namespaces by definition but they can be emulated somehow:
https://stackoverflow.com/a/28535585/1019850
But as you probably use c++ and never c, namespaces could be used directly.
The concrete problem is that you've two times the same function which would be expressed with namespaces a.some_function()
and b.some_function()
.
In Bazel there exist several options how to solve it, I post just short copied snippets, details you've to read on the linked pages.
deps = [
"@gtest//:main",
"//lib:hello-greet",
],
Link: https://docs.bazel.build/versions/master/cpp-use-cases.html
There the snippet is used also for tests but I think that's not important related to your problem.
Then there exist toolchains in Bazel, here is an example:
config_setting(
name = "on_linux",
constraint_values = [
"@bazel_tools//platforms:linux",
],
)
config_setting(
name = "on_windows",
constraint_values = [
"@bazel_tools//platforms:windows",
],
)
bar_binary(
name = "myprog",
srcs = ["mysrc.bar"],
compiler = select({
":on_linux": "//bar_tools:barc_linux",
":on_windows": "//bar_tools:barc_windows",
}),
)
Link: https://docs.bazel.build/versions/master/toolchains.html
As I'm not programming in c or c++ usually it would take me quite some time to dig enough in it to post the solution, so I've to keep it without a real solution but I hope the problem and the way to solve it got a bit clearer.
I'd try it with the second link first, below the first snippet above.
Thanks, but this is not the problem I'm trying to solve. And yes, I do, in fact, use C, not C++. I do use C++ library GoogleTest for unit tests, but code under test is pure C. In any case, the question is about linking, not compiling.
– monnoroch
Jan 11 at 4:10
why you use cc and cpp file-suffix? your problem is related to these files. The recommended way in my answer never mentions compiling, but different ways how to link the 'deps'
– David
Jan 11 at 9:55
add a comment |
Your problem is probably a very basic one, that is related to namespaces and/or extending classes.
c has no namespaces by definition but they can be emulated somehow:
https://stackoverflow.com/a/28535585/1019850
But as you probably use c++ and never c, namespaces could be used directly.
The concrete problem is that you've two times the same function which would be expressed with namespaces a.some_function()
and b.some_function()
.
In Bazel there exist several options how to solve it, I post just short copied snippets, details you've to read on the linked pages.
deps = [
"@gtest//:main",
"//lib:hello-greet",
],
Link: https://docs.bazel.build/versions/master/cpp-use-cases.html
There the snippet is used also for tests but I think that's not important related to your problem.
Then there exist toolchains in Bazel, here is an example:
config_setting(
name = "on_linux",
constraint_values = [
"@bazel_tools//platforms:linux",
],
)
config_setting(
name = "on_windows",
constraint_values = [
"@bazel_tools//platforms:windows",
],
)
bar_binary(
name = "myprog",
srcs = ["mysrc.bar"],
compiler = select({
":on_linux": "//bar_tools:barc_linux",
":on_windows": "//bar_tools:barc_windows",
}),
)
Link: https://docs.bazel.build/versions/master/toolchains.html
As I'm not programming in c or c++ usually it would take me quite some time to dig enough in it to post the solution, so I've to keep it without a real solution but I hope the problem and the way to solve it got a bit clearer.
I'd try it with the second link first, below the first snippet above.
Thanks, but this is not the problem I'm trying to solve. And yes, I do, in fact, use C, not C++. I do use C++ library GoogleTest for unit tests, but code under test is pure C. In any case, the question is about linking, not compiling.
– monnoroch
Jan 11 at 4:10
why you use cc and cpp file-suffix? your problem is related to these files. The recommended way in my answer never mentions compiling, but different ways how to link the 'deps'
– David
Jan 11 at 9:55
add a comment |
Your problem is probably a very basic one, that is related to namespaces and/or extending classes.
c has no namespaces by definition but they can be emulated somehow:
https://stackoverflow.com/a/28535585/1019850
But as you probably use c++ and never c, namespaces could be used directly.
The concrete problem is that you've two times the same function which would be expressed with namespaces a.some_function()
and b.some_function()
.
In Bazel there exist several options how to solve it, I post just short copied snippets, details you've to read on the linked pages.
deps = [
"@gtest//:main",
"//lib:hello-greet",
],
Link: https://docs.bazel.build/versions/master/cpp-use-cases.html
There the snippet is used also for tests but I think that's not important related to your problem.
Then there exist toolchains in Bazel, here is an example:
config_setting(
name = "on_linux",
constraint_values = [
"@bazel_tools//platforms:linux",
],
)
config_setting(
name = "on_windows",
constraint_values = [
"@bazel_tools//platforms:windows",
],
)
bar_binary(
name = "myprog",
srcs = ["mysrc.bar"],
compiler = select({
":on_linux": "//bar_tools:barc_linux",
":on_windows": "//bar_tools:barc_windows",
}),
)
Link: https://docs.bazel.build/versions/master/toolchains.html
As I'm not programming in c or c++ usually it would take me quite some time to dig enough in it to post the solution, so I've to keep it without a real solution but I hope the problem and the way to solve it got a bit clearer.
I'd try it with the second link first, below the first snippet above.
Your problem is probably a very basic one, that is related to namespaces and/or extending classes.
c has no namespaces by definition but they can be emulated somehow:
https://stackoverflow.com/a/28535585/1019850
But as you probably use c++ and never c, namespaces could be used directly.
The concrete problem is that you've two times the same function which would be expressed with namespaces a.some_function()
and b.some_function()
.
In Bazel there exist several options how to solve it, I post just short copied snippets, details you've to read on the linked pages.
deps = [
"@gtest//:main",
"//lib:hello-greet",
],
Link: https://docs.bazel.build/versions/master/cpp-use-cases.html
There the snippet is used also for tests but I think that's not important related to your problem.
Then there exist toolchains in Bazel, here is an example:
config_setting(
name = "on_linux",
constraint_values = [
"@bazel_tools//platforms:linux",
],
)
config_setting(
name = "on_windows",
constraint_values = [
"@bazel_tools//platforms:windows",
],
)
bar_binary(
name = "myprog",
srcs = ["mysrc.bar"],
compiler = select({
":on_linux": "//bar_tools:barc_linux",
":on_windows": "//bar_tools:barc_windows",
}),
)
Link: https://docs.bazel.build/versions/master/toolchains.html
As I'm not programming in c or c++ usually it would take me quite some time to dig enough in it to post the solution, so I've to keep it without a real solution but I hope the problem and the way to solve it got a bit clearer.
I'd try it with the second link first, below the first snippet above.
answered Jan 10 at 0:01
DavidDavid
2,48922130
2,48922130
Thanks, but this is not the problem I'm trying to solve. And yes, I do, in fact, use C, not C++. I do use C++ library GoogleTest for unit tests, but code under test is pure C. In any case, the question is about linking, not compiling.
– monnoroch
Jan 11 at 4:10
why you use cc and cpp file-suffix? your problem is related to these files. The recommended way in my answer never mentions compiling, but different ways how to link the 'deps'
– David
Jan 11 at 9:55
add a comment |
Thanks, but this is not the problem I'm trying to solve. And yes, I do, in fact, use C, not C++. I do use C++ library GoogleTest for unit tests, but code under test is pure C. In any case, the question is about linking, not compiling.
– monnoroch
Jan 11 at 4:10
why you use cc and cpp file-suffix? your problem is related to these files. The recommended way in my answer never mentions compiling, but different ways how to link the 'deps'
– David
Jan 11 at 9:55
Thanks, but this is not the problem I'm trying to solve. And yes, I do, in fact, use C, not C++. I do use C++ library GoogleTest for unit tests, but code under test is pure C. In any case, the question is about linking, not compiling.
– monnoroch
Jan 11 at 4:10
Thanks, but this is not the problem I'm trying to solve. And yes, I do, in fact, use C, not C++. I do use C++ library GoogleTest for unit tests, but code under test is pure C. In any case, the question is about linking, not compiling.
– monnoroch
Jan 11 at 4:10
why you use cc and cpp file-suffix? your problem is related to these files. The recommended way in my answer never mentions compiling, but different ways how to link the 'deps'
– David
Jan 11 at 9:55
why you use cc and cpp file-suffix? your problem is related to these files. The recommended way in my answer never mentions compiling, but different ways how to link the 'deps'
– David
Jan 11 at 9:55
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53950443%2fbuild-unit-test-for-c-with-mocked-dependencies-using-bazel%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
1
why do you tag c++ for a C question?
– phuclv
Jan 6 at 2:43
as far as I see the whole project is in c++ and not c. you use the suffix cpp and also the c++ connector of bazel (they don't have one for c I think). Don't know if usage of fff is possible then but that's another problem.
– David
Jan 9 at 23:07