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;
}







5















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?










share|improve this question




















  • 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




















5















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?










share|improve this question




















  • 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
















5












5








5


2






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?










share|improve this question
















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






share|improve this question















share|improve this question













share|improve this question




share|improve this question








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
















  • 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














1 Answer
1






active

oldest

votes


















0














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.






share|improve this answer
























  • 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












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
});


}
});














draft saved

draft discarded


















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









0














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.






share|improve this answer
























  • 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
















0














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.






share|improve this answer
























  • 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














0












0








0







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.






share|improve this answer













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.







share|improve this answer












share|improve this answer



share|improve this answer










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



















  • 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




















draft saved

draft discarded




















































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.




draft saved


draft discarded














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





















































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







Popular posts from this blog

MongoDB - Not Authorized To Execute Command

How to fix TextFormField cause rebuild widget in Flutter

Npm cannot find a required file even through it is in the searched directory