Создайте модульный тест для C с помощью фиктивных зависимостей, используя bazel - PullRequest
0 голосов
/ 27 декабря 2018

У меня есть кодовая база C, которую я пытаюсь построить с помощью Bazel.Эта кодовая база покрыта модульными тестами, которые используют библиотеку fff для генерации ложных срабатываний функций в Си. Однако фактическая библиотека не важна, у меня проблема с целой концепцией ложных проверок функций.

Прямо сейчас у меня есть make-файл, где я связываю и запускаю свои тесты.Когда я создаю тест, я компилирую и связываю тестируемую библиотеку и сам источник теста.Этот тест также определяет макеты для зависимостей библиотеки.При связывании смоделированные символы преобразуются в ложные реализации, и все работает как положено.Но причина этого в том, что я не связываю фактическую библиотеку зависимостей, я только связываю символы макета, определенные в исходном тексте теста.

ОсновнойВопрос в том, как мне это сделать с Базелем?При связывании двоичного файла для цели cc_test Bazel компилирует и связывает все транзитивные зависимости.Поскольку тестируемая библиотека зависит (через deps) от реальной реализации символа, это реальное определение связано с ложным, и, естественно, я получаю эту ошибку: multiple definition of XXX.

Пример:

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"],
)

Я не совсем новичок в Базеле, но я тоже не эксперт, и, потратив много часов на попытки, я потерпел неудачу.Любой совет, как мне заставить это работать?

1 Ответ

0 голосов
/ 10 января 2019

Ваша проблема, вероятно, очень простая, она связана с пространствами имен и / или расширяющимися классами.

c не имеет пространств имен по определению, но их можно эмулировать каким-либо образом:
https://stackoverflow.com/a/28535585/1019850

Но так как вы, вероятно, используете c ++, а не c, пространства имен можно использовать напрямую.

Конкретная проблема состоит в том, что у вас два раза одна и та же функция, которая будет выражаться в пространствах имен a.some_function() и b.some_function().

В Bazel есть несколько способов ее решения, я публикую только короткие скопированные фрагменты, подробности, которые вы должны прочитать на связанных страницах.

deps = [
    "@gtest//:main",
    "//lib:hello-greet",
],

Ссылка: https://docs.bazel.build/versions/master/cpp-use-cases.html
Там фрагмент используется и для тестов, но я думаю, что это не важно в связи с вашей проблемой.

Тогда в Bazel есть наборы инструментов, вот пример:

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",
    }),
)

Ссылка: https://docs.bazel.build/versions/master/toolchains.html

Поскольку я не программирую на c или c ++, обычно мне требуется довольно много времени, чтобы выкопать в нем достаточно, чтобы опубликовать решение, поэтому я должен оставить его без настоящегорешение, но я надеюсь, что проблемаm, и способ ее решения стал немного яснее.
Я бы попробовал сначала со второй ссылкой, под первым фрагментом выше.

...