Commit 58b63ffe authored by yonghong-song's avatar yonghong-song Committed by GitHub

Merge pull request #1450 from sandip4n/fix-test-libbcc

Fix 'test_libbcc' from failing in certain scenarios
parents 392267f4 c15b5c87
......@@ -17,7 +17,8 @@ add_executable(test_libbcc
test_bpf_table.cc
test_hash_table.cc
test_usdt_args.cc
test_usdt_probes.cc)
test_usdt_probes.cc
utils.cc)
target_link_libraries(test_libbcc bcc-shared dl)
add_test(NAME test_libbcc COMMAND ${TEST_WRAPPER} c_test_all sudo ${CMAKE_CURRENT_BINARY_DIR}/test_libbcc)
......
......@@ -193,6 +193,8 @@ static int mntns_func(void *arg) {
return 0;
}
extern int cmd_scanf(const char *cmd, const char *fmt, ...);
TEST_CASE("resolve symbol addresses for a given PID", "[c_api]") {
struct bcc_symbol sym;
void *resolver = bcc_symcache_new(getpid(), nullptr);
......@@ -230,7 +232,32 @@ TEST_CASE("resolve symbol addresses for a given PID", "[c_api]") {
REQUIRE(sym.module);
REQUIRE(sym.module[0] == '/');
REQUIRE(string(sym.module).find("libc") != string::npos);
REQUIRE(string("strtok") == sym.name);
// In some cases, a symbol may have multiple aliases. Since
// bcc_symcache_resolve() returns only the first alias of a
// symbol, this may not always be "strtok" even if it points
// to the same address.
bool sym_match = (string("strtok") == sym.name);
if (!sym_match) {
uint64_t exp_addr, sym_addr;
char cmd[256];
const char *cmdfmt = "nm %s | grep \" %s$\" | cut -f 1 -d \" \"";
// Find address of symbol by the expected name
sprintf(cmd, cmdfmt, sym.module, "strtok");
REQUIRE(cmd_scanf(cmd, "%lx", &exp_addr) == 0);
// Find address of symbol by the name that was
// returned by bcc_symcache_resolve()
sprintf(cmd, cmdfmt, sym.module, sym.name);
REQUIRE(cmd_scanf(cmd, "%lx", &sym_addr) == 0);
// If both addresses match, they are definitely
// aliases of the same symbol
sym_match = (exp_addr == sym_addr);
}
REQUIRE(sym_match);
}
SECTION("resolve in separate mount namespace") {
......
......@@ -86,6 +86,35 @@ public:
pid_t pid() const { return pid_; }
};
extern int cmd_scanf(const char *cmd, const char *fmt, ...);
static int probe_num_locations(const char *bin_path, const char *func_name) {
int num_locations;
char cmd[512];
const char *cmdfmt = "readelf -n %s | grep -c \"Name: %s$\"";
sprintf(cmd, cmdfmt, bin_path, func_name);
if (cmd_scanf(cmd, "%d", &num_locations) != 0) {
return -1;
}
return num_locations;
}
static int probe_num_arguments(const char *bin_path, const char *func_name) {
int num_arguments;
char cmd[512];
const char *cmdfmt = "readelf -n %s | grep -m 1 -A 2 \" %s$\" | " \
"tail -1 | cut -d \" \" -f 6- | wc -w";
sprintf(cmd, cmdfmt, bin_path, func_name);
if (cmd_scanf(cmd, "%d", &num_arguments) != 0) {
return -1;
}
return num_arguments;
}
TEST_CASE("test listing all USDT probes in Ruby/MRI", "[usdt]") {
size_t mri_probe_count = 0;
......@@ -99,40 +128,63 @@ TEST_CASE("test listing all USDT probes in Ruby/MRI", "[usdt]") {
mri_probe_count = ctx.num_probes();
SECTION("GC static probe") {
auto probe = ctx.get("gc__mark__begin");
auto name = "gc__mark__begin";
auto probe = ctx.get(name);
REQUIRE(probe);
REQUIRE(probe->in_shared_object() == true);
REQUIRE(probe->name() == "gc__mark__begin");
REQUIRE(probe->name() == name);
REQUIRE(probe->provider() == "ruby");
REQUIRE(probe->bin_path().find("/ruby") != std::string::npos);
REQUIRE(probe->num_locations() == 1);
REQUIRE(probe->num_arguments() == 0);
auto bin_path = probe->bin_path();
bool bin_path_match =
(bin_path.find("/ruby") != std::string::npos) ||
(bin_path.find("/libruby") != std::string::npos);
REQUIRE(bin_path_match);
int exp_locations, exp_arguments;
exp_locations = probe_num_locations(bin_path.c_str(), name);
exp_arguments = probe_num_arguments(bin_path.c_str(), name);
REQUIRE(probe->num_locations() == exp_locations);
REQUIRE(probe->num_arguments() == exp_arguments);
REQUIRE(probe->need_enable() == true);
}
SECTION("object creation probe") {
auto probe = ctx.get("object__create");
auto name = "object__create";
auto probe = ctx.get(name);
REQUIRE(probe);
REQUIRE(probe->in_shared_object() == true);
REQUIRE(probe->name() == "object__create");
REQUIRE(probe->name() == name);
REQUIRE(probe->provider() == "ruby");
REQUIRE(probe->bin_path().find("/ruby") != std::string::npos);
REQUIRE(probe->num_locations() == 1);
REQUIRE(probe->num_arguments() == 3);
auto bin_path = probe->bin_path();
bool bin_path_match =
(bin_path.find("/ruby") != std::string::npos) ||
(bin_path.find("/libruby") != std::string::npos);
REQUIRE(bin_path_match);
int exp_locations, exp_arguments;
exp_locations = probe_num_locations(bin_path.c_str(), name);
exp_arguments = probe_num_arguments(bin_path.c_str(), name);
REQUIRE(probe->num_locations() == exp_locations);
REQUIRE(probe->num_arguments() == exp_arguments);
REQUIRE(probe->need_enable() == true);
}
SECTION("array creation probe") {
auto probe = ctx.get("array__create");
auto name = "array__create";
auto probe = ctx.get(name);
REQUIRE(probe);
REQUIRE(probe->name() == "array__create");
REQUIRE(probe->num_locations() == 7);
REQUIRE(probe->num_arguments() == 3);
REQUIRE(probe->name() == name);
auto bin_path = probe->bin_path().c_str();
int exp_locations, exp_arguments;
exp_locations = probe_num_locations(bin_path, name);
exp_arguments = probe_num_arguments(bin_path, name);
REQUIRE(probe->num_locations() == exp_locations);
REQUIRE(probe->num_arguments() == exp_arguments);
REQUIRE(probe->need_enable() == true);
}
}
......@@ -149,16 +201,25 @@ TEST_CASE("test listing all USDT probes in Ruby/MRI", "[usdt]") {
REQUIRE(ctx.num_probes() >= mri_probe_count);
SECTION("get probe in running process") {
auto probe = ctx.get("gc__mark__begin");
auto name = "gc__mark__begin";
auto probe = ctx.get(name);
REQUIRE(probe);
REQUIRE(probe->in_shared_object() == true);
REQUIRE(probe->name() == "gc__mark__begin");
REQUIRE(probe->name() == name);
REQUIRE(probe->provider() == "ruby");
REQUIRE(probe->bin_path().find("/ruby") != std::string::npos);
REQUIRE(probe->num_locations() == 1);
REQUIRE(probe->num_arguments() == 0);
auto bin_path = probe->bin_path();
bool bin_path_match =
(bin_path.find("/ruby") != std::string::npos) ||
(bin_path.find("/libruby") != std::string::npos);
REQUIRE(bin_path_match);
int exp_locations, exp_arguments;
exp_locations = probe_num_locations(bin_path.c_str(), name);
exp_arguments = probe_num_arguments(bin_path.c_str(), name);
REQUIRE(probe->num_locations() == exp_locations);
REQUIRE(probe->num_arguments() == exp_arguments);
REQUIRE(probe->need_enable() == true);
}
}
......
/*
* Copyright (c) 2017 IBM Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <stdarg.h>
#include <stdio.h>
int cmd_scanf(const char *cmd, const char *fmt, ...) {
va_list args;
FILE *pipe;
va_start(args, fmt);
pipe = popen(cmd, "r");
if (pipe == NULL) {
va_end(args);
return -1;
}
vfscanf(pipe, fmt, args);
va_end(args);
pclose(pipe);
return 0;
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment