diff mbox series

[lttng-tools,v2,5/5] Tests: add duplicated providers tests

Message ID 1518213412-16593-6-git-send-email-francis.deslauriers@efficios.com
State Accepted
Delegated to: Jérémie Galarneau
Headers show
Series Support probes with the same name but different event payload | expand

Commit Message

Francis Deslauriers Feb. 9, 2018, 9:56 p.m. UTC
Signed-off-by: Francis Deslauriers <francis.deslauriers at efficios.com>
---
 configure.ac                                    |   1 +
 tests/fast_regression                           |   1 +
 tests/regression/ust/multi-lib/Makefile.am      | 114 +++++++++++
 tests/regression/ust/multi-lib/README           |  21 ++
 tests/regression/ust/multi-lib/callsites.c      |  34 +++
 tests/regression/ust/multi-lib/callsites.h      |  21 ++
 tests/regression/ust/multi-lib/multi-lib-test.c | 251 +++++++++++++++++++++++
 tests/regression/ust/multi-lib/probes.c         |  18 ++
 tests/regression/ust/multi-lib/probes.h         | 195 ++++++++++++++++++
 tests/regression/ust/multi-lib/test_multi_lib   | 262 ++++++++++++++++++++++++
 10 files changed, 918 insertions(+)
 create mode 100644 tests/regression/ust/multi-lib/Makefile.am
 create mode 100644 tests/regression/ust/multi-lib/README
 create mode 100644 tests/regression/ust/multi-lib/callsites.c
 create mode 100644 tests/regression/ust/multi-lib/callsites.h
 create mode 100644 tests/regression/ust/multi-lib/multi-lib-test.c
 create mode 100644 tests/regression/ust/multi-lib/probes.c
 create mode 100644 tests/regression/ust/multi-lib/probes.h
 create mode 100755 tests/regression/ust/multi-lib/test_multi_lib
diff mbox series

Patch

diff --git a/configure.ac b/configure.ac
index b6ea39c..e22872c 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1090,6 +1090,7 @@  AC_CONFIG_FILES([
 	tests/regression/ust/buffers-pid/Makefile
 	tests/regression/ust/periodical-metadata-flush/Makefile
 	tests/regression/ust/multi-session/Makefile
+	tests/regression/ust/multi-lib/Makefile
 	tests/regression/ust/overlap/Makefile
 	tests/regression/ust/overlap/demo/Makefile
 	tests/regression/ust/linking/Makefile
diff --git a/tests/fast_regression b/tests/fast_regression
index bbce068..f76b53d 100644
--- a/tests/fast_regression
+++ b/tests/fast_regression
@@ -21,6 +21,7 @@  regression/tools/regen-statedump/test_ust
 regression/ust/before-after/test_before_after
 regression/ust/buffers-pid/test_buffers_pid
 regression/ust/multi-session/test_multi_session
+regression/ust/multi-lib/test_multi_lib
 regression/ust/nprocesses/test_nprocesses
 regression/ust/overlap/test_overlap
 regression/ust/java-jul/test_java_jul
diff --git a/tests/regression/ust/multi-lib/Makefile.am b/tests/regression/ust/multi-lib/Makefile.am
new file mode 100644
index 0000000..f78ce7f
--- /dev/null
+++ b/tests/regression/ust/multi-lib/Makefile.am
@@ -0,0 +1,114 @@ 
+noinst_SCRIPTS = test_multi_lib
+noinst_PROGRAMS = exec-with-callsites exec-without-callsites
+
+exec_with_callsites_SOURCES = multi-lib-test.c callsites.c
+exec_with_callsites_LDFLAGS = -ldl -lpopt
+exec_with_callsites_CFLAGS = -DHAS_CALLSITES=1
+
+exec_without_callsites_SOURCES = multi-lib-test.c
+exec_without_callsites_LDFLAGS = -ldl -lpopt -llttng-ust
+exec_without_callsites_LDADD = probes.o
+exec_without_callsites_CFLAGS = -DHAS_CALLSITES=0
+
+PROBES_SRC=probes.c probes.h
+PROBES_LDF=-shared -module -llttng-ust -avoid-version -rpath $(abs_builddir)/.libs/
+PROBES_CF=-c -I$(srcdir)/
+
+probes.o: probes.c probes.h
+	$(CC) $(PROBES_CF) -o $@ $<
+
+noinst_LTLIBRARIES = libprobes_a.la libprobes_a_prime.la \
+			libprobes_b.la libprobes_c.la libprobes_c_prime.la \
+			libprobes_d.la libprobes_e.la libprobes_f.la \
+			libprobes_g.la libprobes_h.la libprobes_i.la \
+			libprobes_j.la libprobes_k.la libprobes_l.la \
+			libprobes_m.la libprobes_n.la libprobes_o.la \
+			libprobes_p.la
+
+noinst_LTLIBRARIES += libcallsites_1.la libcallsites_2.la
+
+CALLSITES_SRC=callsites.c callsites.h
+CALLSITES_LDF=-shared -module -llttng-ust -avoid-version -rpath $(abs_builddir)/.libs/
+CALLSITES_CF=-c -I.
+
+libprobes_a_la_SOURCES = $(PROBES_SRC)
+libprobes_a_la_LDFLAGS = $(PROBES_LDF)
+libprobes_a_la_CFLAGS = $(PROBES_CF) -DACTIVATE_PROBES_A
+
+libprobes_a_prime_la_SOURCES = $(PROBES_SRC)
+libprobes_a_prime_la_LDFLAGS = $(PROBES_LDF)
+libprobes_a_prime_la_CFLAGS = $(PROBES_CF) -DACTIVATE_PROBES_A
+
+libprobes_b_la_SOURCES = $(PROBES_SRC)
+libprobes_b_la_LDFLAGS = $(PROBES_LDF)
+libprobes_b_la_CFLAGS = $(PROBES_CF) -DACTIVATE_PROBES_B
+
+libprobes_c_la_SOURCES = $(PROBES_SRC)
+libprobes_c_la_LDFLAGS = $(PROBES_LDF)
+libprobes_c_la_CFLAGS = $(PROBES_CF) -DACTIVATE_PROBES_C
+
+libprobes_c_prime_la_SOURCES = $(PROBES_SRC)
+libprobes_c_prime_la_LDFLAGS = $(PROBES_LDF)
+libprobes_c_prime_la_CFLAGS = $(PROBES_CF) -DACTIVATE_PROBES_C
+
+libprobes_d_la_SOURCES = $(PROBES_SRC)
+libprobes_d_la_LDFLAGS = $(PROBES_LDF)
+libprobes_d_la_CFLAGS = $(PROBES_CF) -DACTIVATE_PROBES_D
+
+libprobes_e_la_SOURCES = $(PROBES_SRC)
+libprobes_e_la_LDFLAGS = $(PROBES_LDF)
+libprobes_e_la_CFLAGS = $(PROBES_CF) -DACTIVATE_PROBES_E
+
+libprobes_f_la_SOURCES = $(PROBES_SRC)
+libprobes_f_la_LDFLAGS = $(PROBES_LDF)
+libprobes_f_la_CFLAGS = $(PROBES_CF) -DACTIVATE_PROBES_F
+
+libprobes_g_la_SOURCES = $(PROBES_SRC)
+libprobes_g_la_LDFLAGS = $(PROBES_LDF)
+libprobes_g_la_CFLAGS = $(PROBES_CF) -DACTIVATE_PROBES_G
+
+libprobes_h_la_SOURCES = $(PROBES_SRC)
+libprobes_h_la_LDFLAGS = $(PROBES_LDF)
+libprobes_h_la_CFLAGS = $(PROBES_CF) -DACTIVATE_PROBES_H
+
+libprobes_i_la_SOURCES = $(PROBES_SRC)
+libprobes_i_la_LDFLAGS = $(PROBES_LDF)
+libprobes_i_la_CFLAGS = $(PROBES_CF) -DACTIVATE_PROBES_I
+
+libprobes_j_la_SOURCES = $(PROBES_SRC)
+libprobes_j_la_LDFLAGS = $(PROBES_LDF)
+libprobes_j_la_CFLAGS = $(PROBES_CF) -DACTIVATE_PROBES_J
+
+libprobes_k_la_SOURCES = $(PROBES_SRC)
+libprobes_k_la_LDFLAGS = $(PROBES_LDF)
+libprobes_k_la_CFLAGS = $(PROBES_CF) -DACTIVATE_PROBES_K
+
+libprobes_l_la_SOURCES = $(PROBES_SRC)
+libprobes_l_la_LDFLAGS = $(PROBES_LDF)
+libprobes_l_la_CFLAGS = $(PROBES_CF) -DACTIVATE_PROBES_L
+
+libprobes_m_la_SOURCES = $(PROBES_SRC)
+libprobes_m_la_LDFLAGS = $(PROBES_LDF)
+libprobes_m_la_CFLAGS = $(PROBES_CF) -DACTIVATE_PROBES_M
+
+libprobes_n_la_SOURCES = $(PROBES_SRC)
+libprobes_n_la_LDFLAGS = $(PROBES_LDF)
+libprobes_n_la_CFLAGS = $(PROBES_CF) -DACTIVATE_PROBES_N
+
+libprobes_o_la_SOURCES = $(PROBES_SRC)
+libprobes_o_la_LDFLAGS = $(PROBES_LDF)
+libprobes_o_la_CFLAGS = $(PROBES_CF) -DACTIVATE_PROBES_O
+
+libprobes_p_la_SOURCES = $(PROBES_SRC)
+libprobes_p_la_LDFLAGS = $(PROBES_LDF)
+libprobes_p_la_CFLAGS = $(PROBES_CF) -DACTIVATE_PROBES_P
+
+libcallsites_1_la_SOURCES = $(CALLSITES_SRC)
+libcallsites_1_la_LDFLAGS = $(CALLSITES_LDF)
+libcallsites_1_la_CFLAGS = $(CALLSITES_CF) -DVALUE=11111
+
+libcallsites_2_la_SOURCES = $(CALLSITES_SRC)
+libcallsites_2_la_LDFLAGS = $(CALLSITES_LDF)
+libcallsites_2_la_CFLAGS = $(CALLSITES_CF) -DVALUE=22222
+
+CLEANFILES=probes.o
diff --git a/tests/regression/ust/multi-lib/README b/tests/regression/ust/multi-lib/README
new file mode 100644
index 0000000..15b969f
--- /dev/null
+++ b/tests/regression/ust/multi-lib/README
@@ -0,0 +1,21 @@ 
+Those test cases are designed to test the support for loading and unloading
+probe providers and callsites at run time during tracing. One test case also
+tests the event payload comparaison functions.
+
+Testing build artefacts:
+------------------------
+
+./exec-with-callsites
+	Test binary built with tracepoint callsites
+
+./exec-without-callsites
+	Test binary built without tracepoint callsites
+
+/.libs/libprobe_*.so:
+	Libraries containing slight variations of probe providers for the same
+	tracepoint name. Note that the file /.libs/libprobes_a_prime.so has the same
+	content as .libs/libprobes_a.so likewise for libprobes_c_prime.so
+
+/.libs/libcallsites_*.so
+  Libraries containing tracepoint callsites. The user must dlopen the library
+  and use dlsym to get an handle on the function that calls the tracepoint.
diff --git a/tests/regression/ust/multi-lib/callsites.c b/tests/regression/ust/multi-lib/callsites.c
new file mode 100644
index 0000000..4b61ac2
--- /dev/null
+++ b/tests/regression/ust/multi-lib/callsites.c
@@ -0,0 +1,34 @@ 
+/*
+ * Copyright (C) - 2018 Francis Deslauriers <francis.deslauriers at efficios.com>
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by the
+ * Free Software Foundation; version 2.1 of the License.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA
+ */
+
+#define TRACEPOINT_DEFINE
+#define TRACEPOINT_PROBE_DYNAMIC_LINKAGE
+#include "probes.h"
+
+#include <stdint.h>
+#include <stdio.h>
+#include <time.h>
+#include <pthread.h>
+
+#ifndef VALUE
+#define VALUE (-1)
+#endif
+
+void call_tracepoint(void) {
+	tracepoint(multi, tp, VALUE);
+}
+
diff --git a/tests/regression/ust/multi-lib/callsites.h b/tests/regression/ust/multi-lib/callsites.h
new file mode 100644
index 0000000..547a6a6
--- /dev/null
+++ b/tests/regression/ust/multi-lib/callsites.h
@@ -0,0 +1,21 @@ 
+/*
+ * Copyright (C) - 2018 Francis Deslauriers <francis.deslauriers at efficios.com>
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by the
+ * Free Software Foundation; version 2.1 of the License.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA
+ */
+
+#ifndef CALLSITES_H
+#define CALLSITES_H
+void call_tracepoint();
+#endif /* CALLSITES_H */
diff --git a/tests/regression/ust/multi-lib/multi-lib-test.c b/tests/regression/ust/multi-lib/multi-lib-test.c
new file mode 100644
index 0000000..856b6d1
--- /dev/null
+++ b/tests/regression/ust/multi-lib/multi-lib-test.c
@@ -0,0 +1,251 @@ 
+/*
+ * Copyright (C) - 2018 Francis Deslauriers <francis.deslauriers at efficios.com>
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by the
+ * Free Software Foundation; version 2.1 of the License.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA
+ */
+
+#include <dlfcn.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <popt.h>
+
+#if HAS_CALLSITES
+	#include "callsites.h"
+#endif
+
+void exec_callsite()
+{
+#if HAS_CALLSITES
+	call_tracepoint();
+#endif
+}
+
+void print_list(void)
+{
+	fprintf(stderr, "Test list (-t X):\n");
+	fprintf(stderr, "\t0: dlopen all libraries pass in arguments and execute "
+			"the callsite. \n");
+	fprintf(stderr, "\t1: simulate the upgrade of a probe provider using dlopen and dlclose \n");
+	fprintf(stderr, "\t2: simulate the upgrade of a library containing the callsites using dlopen and dlclose \n");
+}
+
+
+int dl_open_all(int nb_libraries, char **libraries)
+{
+	int i, ret = 0;
+	void **handles;
+	handles = malloc(nb_libraries * sizeof(void *));
+	if (!handles) {
+		ret = -1;
+		goto error;
+	}
+
+	/* Iterate over the libs to dlopen and save the handles. */
+	for (i = 0; i < nb_libraries; i++) {
+		handles[i] = dlopen(libraries[i], RTLD_NOW);
+		if (!handles[i]) {
+			ret = -1;
+			goto error;
+		}
+	}
+
+	exec_callsite();
+error:
+	return ret;
+}
+
+/*
+ * Takes 2 paths to libraries, dlopen() the first, trace, dlopen() the second,
+ * and dlclose the first to simulate the upgrade of a library.
+ */
+int upgrade_lib(int nb_libraries, char **libraries)
+{
+	int i, ret = 0;
+	void **handles;
+	if (nb_libraries != 2) {
+		ret = -1;
+		goto error;
+	}
+
+	handles = malloc(nb_libraries * sizeof(void *));
+	if (!handles) {
+		ret = -1;
+		goto error;
+	}
+
+	/* Iterate over the libs to dlopen and save the handles. */
+	for (i = 0; i < nb_libraries; i++) {
+		handles[i] = dlopen(libraries[i], RTLD_NOW);
+		if (!handles[i]) {
+			ret = -1;
+			goto error;
+		}
+
+		exec_callsite();
+	}
+	ret = dlclose(handles[0]);
+	if (ret) {
+		goto error;
+	}
+
+	exec_callsite();
+
+error:
+	return ret;
+}
+
+/*
+ * Simulate the upgrade of a library containing a callsite.
+ * Receives two libraries containing callsites for the same tracepoint.
+ */
+int upgrade_callsite(int nb_libraries, char **libraries)
+{
+	int i, ret = 0;
+	void *handles[2];
+	void (*fct_ptr[2])(void);
+
+	if (nb_libraries != 2) {
+		ret = -1;
+		goto error;
+	}
+
+	/* Load the probes in the first library. */
+	handles[0] = dlopen(libraries[0], RTLD_NOW);
+	if (!handles[0]) {
+		ret = -1;
+		goto error;
+	}
+
+	/*
+	 * Get the pointer to the old function containing the callsite and call it.
+	 */
+	fct_ptr[0] = dlsym(handles[0], "call_tracepoint");
+	if (!fct_ptr[0]) {
+		ret = -1;
+		goto error;
+	}
+	fct_ptr[0]();
+
+	/* Load the new callsite library. */
+	handles[1] = dlopen(libraries[1], RTLD_NOW);
+	if (!handles[1]) {
+		ret = -1;
+		goto error;
+	}
+
+	/*
+	 * Get the pointer to the new function containing the callsite and call it.
+	 */
+	fct_ptr[1] = dlsym(handles[1], "call_tracepoint");
+	if (!fct_ptr[1]) {
+		ret = -1;
+		goto error;
+	}
+	fct_ptr[1]();
+
+	/* Unload the old callsite library. */
+	ret = dlclose(handles[0]);
+	if (ret) {
+		goto error;
+	}
+
+	/* Call the function containing the callsite in the new library. */
+	fct_ptr[1]();
+
+	ret = dlclose(handles[1]);
+	if (ret) {
+		goto error;
+	}
+
+error:
+	return ret;
+}
+
+int main(int argc, const char **argv) {
+	int c, ret, i, test = -1, nb_libraries = 0;
+	char **libraries = NULL;
+	poptContext optCon;
+
+	struct poptOption optionsTable[] = {
+		{ "test", 't', POPT_ARG_INT, &test, 0,
+			"Test to run", NULL },
+		{ "list", 'l', 0, 0, 'l',
+			"List of tests (-t X)", NULL },
+		POPT_AUTOHELP
+		{ NULL, 0, 0, NULL, 0 }
+	};
+
+	optCon = poptGetContext(NULL, argc, argv, optionsTable, 0);
+
+	if (argc < 2) {
+		poptPrintUsage(optCon, stderr, 0);
+		ret = -1;
+		goto error;
+	}
+
+	ret = 0;
+
+	while ((c = poptGetNextOpt(optCon)) >= 0) {
+		switch(c) {
+		case 'l':
+			print_list();
+			goto error;
+		}
+	}
+	/* Populate the libraries array with the arguments passed to the process. */
+	while (poptPeekArg(optCon) != NULL) {
+		nb_libraries++;
+		libraries = realloc(libraries, nb_libraries * sizeof(char *));
+		if (!libraries) {
+			ret = -1;
+			goto error;
+		}
+		libraries[nb_libraries-1] = (char*)poptGetArg(optCon);
+	}
+
+	switch(test) {
+	case 0:
+#if HAS_CALLSITES
+		ret = dl_open_all(nb_libraries, libraries);
+#else
+		fprintf(stderr, "Test not implemented for configuration "
+				"(HAS_CALLSITES=%d)\n", HAS_CALLSITES == 1);
+#endif
+		break;
+	case 1:
+#if HAS_CALLSITES
+		ret = upgrade_lib(nb_libraries, libraries);
+#else
+		fprintf(stderr, "Test not implemented for configuration "
+				"(HAS_CALLSITES=%d)\n", HAS_CALLSITES == 1);
+#endif
+		break;
+	case 2:
+#if !HAS_CALLSITES
+		ret = upgrade_callsite(nb_libraries, libraries);
+#else
+		fprintf(stderr, "Test not implemented for configuration "
+				"(HAS_CALLSITES=%d)\n", HAS_CALLSITES == 1);
+#endif
+		break;
+	default:
+		fprintf(stderr, "Test %d not implemented\n", test);
+		ret = -1;
+		break;
+	}
+error:
+	poptFreeContext(optCon);
+	return ret;
+}
diff --git a/tests/regression/ust/multi-lib/probes.c b/tests/regression/ust/multi-lib/probes.c
new file mode 100644
index 0000000..3ee9164
--- /dev/null
+++ b/tests/regression/ust/multi-lib/probes.c
@@ -0,0 +1,18 @@ 
+/*
+ * Copyright (C) - 2018 Francis Deslauriers <francis.deslauriers at efficios.com>
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by the
+ * Free Software Foundation; version 2.1 of the License.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA
+ */
+#define TRACEPOINT_CREATE_PROBES
+#include "probes.h"
diff --git a/tests/regression/ust/multi-lib/probes.h b/tests/regression/ust/multi-lib/probes.h
new file mode 100644
index 0000000..110686c
--- /dev/null
+++ b/tests/regression/ust/multi-lib/probes.h
@@ -0,0 +1,195 @@ 
+/*
+ * Copyright (C) - 2018 Francis Deslauriers <francis.deslauriers at efficios.com>
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by the
+ * Free Software Foundation; version 2.1 of the License.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA
+ */
+
+#undef TRACEPOINT_PROVIDER
+#define TRACEPOINT_PROVIDER multi
+
+#undef TRACEPOINT_INCLUDE
+#define TRACEPOINT_INCLUDE "./probes.h"
+
+#if !defined(PROBES_H) || defined(TRACEPOINT_HEADER_MULTI_READ)
+#define PROBES_H
+
+#include <lttng/tracepoint.h>
+
+#if defined(ACTIVATE_PROBES_A)
+TRACEPOINT_EVENT(multi, tp,
+    TP_ARGS(unsigned long, arg),
+    TP_FIELDS(
+        ctf_integer(unsigned long, arg_long_A, arg)
+    )
+)
+#elif defined(ACTIVATE_PROBES_B)
+TRACEPOINT_EVENT(multi, tp,
+    TP_ARGS(unsigned long, arg),
+    TP_FIELDS(
+        ctf_integer(unsigned long, arg_long_B, arg)
+        ctf_float(float, arg_float_B, (float) arg)
+    )
+)
+#elif defined(ACTIVATE_PROBES_C)
+TRACEPOINT_ENUM(multi, enum_a,
+    TP_ENUM_VALUES(
+        ctf_enum_value("FIELD_A", 0)
+        ctf_enum_value("FIELD_B", 1)
+        ctf_enum_range("RANGE_C", 2, 10)
+    )
+)
+TRACEPOINT_EVENT(multi, tp,
+    TP_ARGS(unsigned long, arg),
+    TP_FIELDS(
+        ctf_enum(multi, enum_a, short, enum_short_C,  0)
+        ctf_enum(multi, enum_a, int, enum_int_C,  1)
+        ctf_enum(multi, enum_a, unsigned long, enum_long_C,  2)
+    )
+)
+#elif defined(ACTIVATE_PROBES_D)
+TRACEPOINT_ENUM(multi, enum_a,
+    TP_ENUM_VALUES(
+        ctf_enum_value("FIELD_A", 0)
+        ctf_enum_value("FIELD_B", 1)
+        ctf_enum_range("RANGE_C_PRIME", 2, 10)
+    )
+)
+TRACEPOINT_EVENT(multi, tp,
+    TP_ARGS(unsigned long, arg),
+    TP_FIELDS(
+        ctf_enum(multi, enum_a, int, enum_int_D,  1)
+        ctf_enum(multi, enum_a, short, enum_short_D,  0)
+        ctf_enum(multi, enum_a, unsigned long, enum_long_D,  2)
+    )
+)
+#elif defined(ACTIVATE_PROBES_E)
+/*
+ * Here we declare tracepoints really similar to one another but are different.
+ * This is meant to test tracepoint comparaison code.
+ */
+TRACEPOINT_EVENT(multi, tp,
+    TP_ARGS(unsigned long, arg),
+    TP_FIELDS(
+        ctf_integer(unsigned long, arg_long, arg)
+    )
+)
+#elif defined(ACTIVATE_PROBES_F)
+TRACEPOINT_EVENT(multi, tp,
+    TP_ARGS(unsigned long, arg),
+    TP_FIELDS(
+        ctf_integer(long, arg_long, arg)
+    )
+)
+#elif defined(ACTIVATE_PROBES_G)
+TRACEPOINT_EVENT(multi, tp,
+    TP_ARGS(unsigned long, arg),
+    TP_FIELDS(
+        ctf_integer_hex(long, arg_long, arg)
+    )
+)
+#elif defined(ACTIVATE_PROBES_H)
+TRACEPOINT_EVENT(multi, tp,
+    TP_ARGS(unsigned long, arg),
+    TP_FIELDS(
+        ctf_integer_hex(short, arg_long, arg)
+    )
+)
+#elif defined(ACTIVATE_PROBES_I)
+TRACEPOINT_EVENT(multi, tp,
+    TP_ARGS(unsigned long, arg),
+    TP_FIELDS(
+        ctf_integer_hex(int, arg_long, arg)
+    )
+)
+#elif defined(ACTIVATE_PROBES_J)
+TRACEPOINT_EVENT(multi, tp,
+    TP_ARGS(unsigned long, arg),
+    TP_FIELDS(
+        ctf_float(float, arg_float, (float) arg)
+    )
+)
+#elif defined(ACTIVATE_PROBES_K)
+TRACEPOINT_EVENT(multi, tp,
+    TP_ARGS(unsigned long, arg),
+    TP_FIELDS(
+        ctf_float(double, arg_float, (double) arg)
+    )
+)
+#elif defined(ACTIVATE_PROBES_L)
+TRACEPOINT_ENUM(multi, enum_a,
+    TP_ENUM_VALUES(
+        ctf_enum_value("FIELD_A", 0)
+        ctf_enum_value("FIELD_B", 1)
+        ctf_enum_range("RANGE_C", 2, 10)
+    )
+)
+TRACEPOINT_EVENT(multi, tp,
+    TP_ARGS(unsigned long, arg),
+    TP_FIELDS(
+        ctf_enum(multi, enum_a, int, enum_int,  1)
+    )
+)
+#elif defined(ACTIVATE_PROBES_M)
+TRACEPOINT_ENUM(multi, enum_a,
+    TP_ENUM_VALUES(
+        ctf_enum_value("FIELD_A", 0)
+        ctf_enum_value("FIELD_B", 1)
+        ctf_enum_range("RANGE_C", 2, 10)
+    )
+)
+TRACEPOINT_EVENT(multi, tp,
+    TP_ARGS(unsigned long, arg),
+    TP_FIELDS(
+        ctf_enum(multi, enum_a, long, enum_int,  1)
+    )
+)
+#elif defined(ACTIVATE_PROBES_N)
+TRACEPOINT_ENUM(multi, enum_a,
+    TP_ENUM_VALUES(
+        ctf_enum_value("FIELD_A", 0)
+        ctf_enum_value("FIELD_B", 1)
+        ctf_enum_range("RANGE_C", 2, 10)
+    )
+)
+TRACEPOINT_EVENT(multi, tp,
+    TP_ARGS(unsigned long, arg),
+    TP_FIELDS(
+        ctf_enum(multi, enum_a, short, enum_int,  1)
+    )
+)
+#elif defined(ACTIVATE_PROBES_O)
+TRACEPOINT_EVENT(multi, tp,
+    TP_ARGS(unsigned long, arg),
+    TP_FIELDS(
+        ctf_string(arg_string, "string")
+    )
+)
+#elif defined(ACTIVATE_PROBES_P)
+TRACEPOINT_EVENT(multi, tp,
+    TP_ARGS(unsigned long, arg),
+    TP_FIELDS(
+        ctf_string(my_arg_string, "string")
+    )
+)
+#else
+TRACEPOINT_EVENT(multi, tp,
+    TP_ARGS(unsigned long, arg),
+    TP_FIELDS(
+    )
+)
+#endif
+
+#endif /* PROBES_H */
+
+#include <lttng/tracepoint-event.h>
diff --git a/tests/regression/ust/multi-lib/test_multi_lib b/tests/regression/ust/multi-lib/test_multi_lib
new file mode 100755
index 0000000..d4c2880
--- /dev/null
+++ b/tests/regression/ust/multi-lib/test_multi_lib
@@ -0,0 +1,262 @@ 
+#!/bin/bash
+#
+# Copyright (C) - 2018 Francis Deslauriers <francis.deslauriers at efficios.com>
+#
+# This library is free software; you can redistribute it and/or modify it under
+# the terms of the GNU Lesser General Public License as published by the Free
+# Software Foundation; version 2.1 of the License.
+#
+# This library is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+# FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
+# details.
+#
+# You should have received a copy of the GNU Lesser General Public License
+# along with this library; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA
+
+TEST_DESC="UST - Dynamic loading and unloading of libraries"
+
+CURDIR=$(dirname $0)/
+TESTDIR=$CURDIR/../../..
+SESSION_NAME="multi_lib"
+
+EXEC_NAME_WITH_CALLSITES=./exec-with-callsites
+EXEC_NAME_WITHOUT_CALLSITES=./exec-without-callsites
+SO_DIR=$CURDIR/.libs/
+SO_PROBES_A=$SO_DIR/libprobes_a.so
+SO_PROBES_A_PRIME=$SO_DIR/libprobes_a_prime.so
+SO_PROBES_B=$SO_DIR/libprobes_b.so
+SO_PROBES_C=$SO_DIR/libprobes_c.so
+SO_PROBES_C_PRIME=$SO_DIR/libprobes_c_prime.so
+SO_PROBES_D=$SO_DIR/libprobes_d.so
+SO_CALLSITE_1=$SO_DIR/libcallsites_1.so
+SO_CALLSITE_2=$SO_DIR/libcallsites_2.so
+
+NUM_TESTS=55
+
+source $TESTDIR/utils/utils.sh
+
+test_dlopen_same_provider_name_same_event()
+{
+	local event_name="multi:tp"
+	diag "dlopen 2 providers, same event name, same payload"
+
+	enable_ust_lttng_event_ok $SESSION_NAME "$event_name"
+
+	start_lttng_tracing_ok $SESSION_NAME
+
+	$EXEC_NAME_WITH_CALLSITES -t 0 $SO_PROBES_A $SO_PROBES_A_PRIME
+
+	stop_lttng_tracing_ok $SESSION_NAME
+
+	# Expect 2 identical events in the trace
+	trace_match_only $event_name 2 $TRACE_PATH
+
+	# Expect a single event ID in the metadata
+	validate_metadata_event $event_name 1 $TRACE_PATH
+
+	return $?
+}
+
+test_dlopen_same_provider_name_different_event()
+{
+	local event_name="multi:tp"
+	# Regular expression for event tp with one argument: arg_long
+	local event_a_payload_exp="^.*$event_name.*arg_long_A.*"
+	# Regular expression for event tp with two arguments: arg_long and
+	# arg_float
+	local event_b_payload_exp="^.*$event_name.*arg_long_B.*arg_float_B.*"
+	diag "dlopen 2 providers, same event name, different payload"
+
+	enable_ust_lttng_event_ok $SESSION_NAME "$event_name"
+
+	start_lttng_tracing_ok $SESSION_NAME
+
+	$EXEC_NAME_WITH_CALLSITES -t 0 $SO_PROBES_A $SO_PROBES_B
+
+	stop_lttng_tracing_ok $SESSION_NAME
+
+	# Expect 2 identical events in the trace
+	trace_match_only $event_name 2 $TRACE_PATH
+
+	# Expect 2 events ID in the metadata
+	validate_metadata_event $event_name 2 $TRACE_PATH
+
+	# Expect 2 events with different payloads
+	validate_trace_exp $event_a_payload_exp $TRACE_PATH
+	validate_trace_exp $event_b_payload_exp $TRACE_PATH
+
+	return $?
+}
+
+test_dlopen_same_provider_name_same_enum()
+{
+	local event_name="multi:tp"
+	# Regular expression for event tp with one argument: arg_long
+	local event_c_payload_exp="^.*$event_name.*enum_int_C.*"
+	# Regular expression for event tp with two arguments: arg_long and
+	# arg_float
+	local event_d_payload_exp="^.*$event_name.*enum_int_D.*"
+	diag "dlopen 2 providers, same event name, same enum definition"
+
+	enable_ust_lttng_event_ok $SESSION_NAME "$event_name"
+
+	start_lttng_tracing_ok $SESSION_NAME
+
+	$EXEC_NAME_WITH_CALLSITES -t 0 $SO_PROBES_C $SO_PROBES_C_PRIME
+
+	stop_lttng_tracing_ok $SESSION_NAME
+
+	# Expect 2 identical events in the trace
+	trace_match_only $event_name 2 $TRACE_PATH
+
+	# Expect 2 events ID in the metadata
+	validate_metadata_event $event_name 1 $TRACE_PATH
+
+	return $?
+}
+
+test_dlopen_same_provider_name_different_enum()
+{
+	local event_name="multi:tp"
+	# Regular expression for event tp with one argument: arg_long
+	local event_c_payload_exp="^.*$event_name.*enum_int_C.*"
+	# Regular expression for event tp with two arguments: arg_long and
+	# arg_float
+	local event_d_payload_exp="^.*$event_name.*enum_int_D.*"
+	diag "dlopen 2 providers, same event name, different enum definition"
+
+	enable_ust_lttng_event_ok $SESSION_NAME "$event_name"
+
+	start_lttng_tracing_ok $SESSION_NAME
+
+	$EXEC_NAME_WITH_CALLSITES -t 0 $SO_PROBES_C $SO_PROBES_D
+
+	stop_lttng_tracing_ok $SESSION_NAME
+
+	# Expect 2 identical events in the trace
+	trace_match_only $event_name 2 $TRACE_PATH
+
+	# Expect 2 events ID in the metadata
+	validate_metadata_event $event_name 2 $TRACE_PATH
+
+	# Expect 2 events with different payloads
+	validate_trace_exp $event_c_payload_exp $TRACE_PATH
+	validate_trace_exp $event_d_payload_exp $TRACE_PATH
+
+	return $?
+}
+
+test_upgrade_probes_dlopen_dclose()
+{
+	local event_name="multi:tp"
+	diag "Upgrade probe provider using dlopen/dlclose during tracing"
+
+	enable_ust_lttng_event_ok $SESSION_NAME "$event_name"
+
+	start_lttng_tracing_ok $SESSION_NAME
+
+	$EXEC_NAME_WITH_CALLSITES -t 1 $SO_PROBES_A $SO_PROBES_B
+
+	stop_lttng_tracing_ok $SESSION_NAME
+
+	# Expect 2 identical events in the trace
+	trace_match_only $event_name 4 $TRACE_PATH
+
+	# Expect 2 events ID in the metadata
+	validate_metadata_event $event_name 2 $TRACE_PATH
+
+	return $?
+}
+
+test_upgrade_callsites_dlopen_dclose()
+{
+	local event_name="multi:tp"
+	diag "Upgrade callsite using dlopen/dlclose during tracing"
+
+	enable_ust_lttng_event_ok $SESSION_NAME "$event_name"
+
+	start_lttng_tracing_ok $SESSION_NAME
+
+	$EXEC_NAME_WITHOUT_CALLSITES -t 2 $SO_CALLSITE_1 $SO_CALLSITE_2
+
+	stop_lttng_tracing_ok $SESSION_NAME
+
+	# Expect 2 identical events in the trace
+	trace_match_only $event_name 3 $TRACE_PATH
+
+	# Expect 2 events ID in the metadata
+	validate_metadata_event $event_name 1 $TRACE_PATH
+
+	return $?
+}
+
+test_event_field_comparaison()
+{
+	local event_name="multi:tp"
+	diag "Load mutliple events with slight variations in the field descriptions."
+
+	local library_prefix="libprobes_"
+	local nb_libs=0
+	local library_list=" "
+	# Concatenate all the probe libraries in a string.
+	for postfix in {a..p}; do
+		library_list="$library_list $SO_DIR/$library_prefix$postfix.so"
+		let nb_libs+=1
+	done
+
+	enable_ust_lttng_event_ok $SESSION_NAME "$event_name"
+
+	start_lttng_tracing_ok $SESSION_NAME
+
+	$EXEC_NAME_WITH_CALLSITES -t 0 $library_list
+
+	stop_lttng_tracing_ok $SESSION_NAME
+
+	# Expect $nb_libs identical events in the trace
+	trace_match_only $event_name $nb_libs $TRACE_PATH
+
+	# Expect $nb_libs events ID in the metadata
+	validate_metadata_event $event_name $nb_libs $TRACE_PATH
+
+	return $?
+}
+
+
+plan_tests $NUM_TESTS
+
+print_test_banner "$TEST_DESC"
+
+TESTS=(
+	"test_dlopen_same_provider_name_same_event"
+	"test_dlopen_same_provider_name_different_event"
+	"test_dlopen_same_provider_name_different_enum"
+	"test_dlopen_same_provider_name_same_enum"
+	"test_event_field_comparaison"
+	"test_upgrade_probes_dlopen_dclose"
+	"test_upgrade_callsites_dlopen_dclose"
+)
+
+TEST_COUNT=${#TESTS[@]}
+i=0
+
+start_lttng_sessiond
+
+while [ "$i" -lt "$TEST_COUNT" ]; do
+
+	TRACE_PATH=$(mktemp -d)
+
+	create_lttng_session_ok $SESSION_NAME $TRACE_PATH
+
+	# Execute test
+	${TESTS[$i]}
+
+	destroy_lttng_session_ok $SESSION_NAME
+
+	rm -rf $TRACE_PATH
+
+	let "i++"
+done
+
+stop_lttng_sessiond