Skip to content

Commit 74c83d1

Browse files
committed
runtime_shell: Adding test for go plugins
This commit adds a runtime shell test for the go plugin interface. A dummy go output plugin is added to the directories, and a test that builds the plugin shared object and then tests that it works and writes the output. This test ensures that the go proxy interface is working as expected. This was tested in the devcontainer using ctest. Signed-off-by: jmccormick7 <jcm258@case.edu>
1 parent 5448880 commit 74c83d1

File tree

9 files changed

+325
-1
lines changed

9 files changed

+325
-1
lines changed

tests/runtime_shell/CMakeLists.txt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ set(UNIT_TESTS_SH
1515
in_syslog_uds_stream_plaintext_expect.sh
1616
processor_conditional.sh
1717
processor_invalid.sh
18+
proxy_logs_expect.sh
1819
)
1920

2021
# Prepare list of unit tests
@@ -27,6 +28,7 @@ foreach(script ${UNIT_TESTS_SH})
2728
"FLB_ROOT=${PROJECT_SOURCE_DIR};\
2829
FLB_RUNTIME_SHELL_PATH=${CMAKE_CURRENT_SOURCE_DIR};\
2930
FLB_RUNTIME_SHELL_CONF=${CMAKE_CURRENT_SOURCE_DIR}/conf;\
30-
FLB_BIN=${CMAKE_BINARY_DIR}/bin/fluent-bit"
31+
FLB_BIN=${CMAKE_BINARY_DIR}/bin/fluent-bit;\
32+
FLB_BUILD=${CMAKE_BINARY_DIR}"
3133
)
3234
endforeach()
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
[SERVICE]
2+
Flush 1
3+
Grace 2
4+
Log_Level info
5+
Daemon Off
6+
7+
[INPUT]
8+
Name dummy
9+
Dummy {"message": "test log entry", "level": "info"}
10+
Samples 3
11+
Tag test.logs
12+
13+
[OUTPUT]
14+
Name test_logs_go
15+
Match test.logs
16+
17+
[OUTPUT]
18+
Name file
19+
Match test.logs
20+
File ${SIGNAL_FILE_PATH}
21+
mkdir on

tests/runtime_shell/conf/proxy_metrics_test.conf

Whitespace-only changes.
Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
#!/bin/bash
2+
3+
# Build script for Go test plugins
4+
set -e
5+
6+
GO_PLUGIN_DIR="${FLB_ROOT}/tests/runtime_shell/go_plugins"
7+
BUILD_DIR="${FLB_ROOT}/build"
8+
9+
install_go_if_needed() {
10+
if ! command -v go &> /dev/null; then
11+
echo "Go not found, installing Go..."
12+
13+
ARCH=$(uname -m)
14+
case $ARCH in
15+
x86_64) GO_ARCH="amd64" ;;
16+
aarch64|arm64) GO_ARCH="arm64" ;;
17+
*) echo "Unsupported architecture: $ARCH"; exit 1 ;;
18+
esac
19+
20+
OS=$(uname -s | tr '[:upper:]' '[:lower:]')
21+
GO_VERSION="1.25.4"
22+
GO_TARBALL="go${GO_VERSION}.${OS}-${GO_ARCH}.tar.gz"
23+
GO_URL="https://golang.org/dl/${GO_TARBALL}"
24+
25+
echo "Downloading Go from $GO_URL..."
26+
27+
TEMP_DIR=$(mktemp -d)
28+
cd "$TEMP_DIR"
29+
30+
if command -v curl > /dev/null 2>&1; then
31+
curl -L -O "$GO_URL"
32+
else
33+
echo "Neither wget nor curl is available to download Go."
34+
exit 1
35+
fi
36+
37+
echo "Extracting Go tarball..."
38+
ls -la
39+
40+
if [ ! -f "$GO_TARBALL" ]; then
41+
echo "Failed to download Go tarball."
42+
exit 1
43+
fi
44+
45+
tar -xzf "$GO_TARBALL"
46+
47+
if [ -w "/usr/local" ]; then
48+
sudo rm -rf /usr/local/go
49+
sudo mv go /usr/local/go
50+
export PATH="/usr/local/go/bin:$PATH"
51+
else
52+
echo "No write permission to /usr/local. Installing Go to $HOME/.local/go"
53+
mkdir -p "$HOME/.local"
54+
rm -rf "$HOME/.local/go"
55+
mv go "$HOME/.local/go"
56+
export PATH="$HOME/.local/go/bin:$PATH"
57+
fi
58+
cd - > /dev/null
59+
rm -rf "$TEMP_DIR"
60+
echo "Go installed successfully."
61+
go version
62+
else
63+
echo "Go is already installed."
64+
fi
65+
}
66+
67+
verify_go_cgo() {
68+
echo "Verifying Go CGO support..."
69+
if ! go env CGO_ENABLED | grep -q "1"; then
70+
echo "Warning: CGO is not enabled. Attempting to enable CGO..."
71+
export CGO_ENABLED=1
72+
fi
73+
74+
TEMP_GO_FILE=$(mktemp --suffix=.go)
75+
cat > "$TEMP_GO_FILE" << 'EOF'
76+
package main
77+
import "C"
78+
//export TestFunc
79+
func TestFunc() {}
80+
func main() {}
81+
EOF
82+
TEMP_SO_FILE=$(mktemp --suffix=.so)
83+
if go build -buildmode=c-shared -o "$TEMP_SO_FILE" "$TEMP_GO_FILE" 2> /dev/null; then
84+
echo "CGO is enabled and working."
85+
rm -f "$TEMP_GO_FILE" "$TEMP_SO_FILE"
86+
else
87+
echo "Error: CGO is not enabled or not working properly. Please ensure you have a C compiler installed."
88+
rm -f "$TEMP_GO_FILE" "$TEMP_SO_FILE"
89+
exit 1
90+
fi
91+
}
92+
93+
build_go_plugins() {
94+
echo "Building Go test plugins..."
95+
96+
echo "Building logs output plugin..."
97+
cd "$GO_PLUGIN_DIR"
98+
CGO_ENABLED=1 GO111MODULE=on go build -buildmode=c-shared -v -ldflags="-s -w" -o $BUILD_DIR/test_logs_go.so logs_output.go
99+
if [ $? -eq 0 ]; then
100+
echo "Go test plugins built successfully!"
101+
echo "Logs plugin: $BUILD_DIR/test_logs_go.so"
102+
else
103+
echo "Failed to build Go test plugins."
104+
exit 1
105+
fi
106+
}
107+
108+
echo "Setting up Go build environment..."
109+
install_go_if_needed
110+
verify_go_cgo
111+
build_go_plugins
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
module github.com/fluent/fluent-bit/tests/runtime_shell/go_plugins
2+
3+
go 1.25.1
4+
5+
require (
6+
github.com/fluent/fluent-bit-go v0.0.0-20230731091245-a7a013e2473c
7+
github.com/ugorji/go/codec v1.1.7 // indirect
8+
)
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
github.com/fluent/fluent-bit-go v0.0.0-20230731091245-a7a013e2473c h1:yKN46XJHYC/gvgH2UsisJ31+n4K3S7QYZSfU2uAWjuI=
2+
github.com/fluent/fluent-bit-go v0.0.0-20230731091245-a7a013e2473c/go.mod h1:L92h+dgwElEyUuShEwjbiHjseW410WIcNz+Bjutc8YQ=
3+
github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw=
4+
github.com/ugorji/go/codec v1.1.7 h1:2SvQaVZ1ouYrrKKwoSk2pzd4A9evlKJb9oTL+OaLUSs=
5+
github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY=
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
package main
2+
3+
import (
4+
"C"
5+
"fmt"
6+
"unsafe"
7+
8+
"github.com/fluent/fluent-bit-go/output"
9+
)
10+
11+
//export FLBPluginRegister
12+
func FLBPluginRegister(def unsafe.Pointer) int {
13+
// Register as logs-only output plugin
14+
return output.FLBPluginRegister(def, "test_logs_go", "Test Go Output Plugin for Logs")
15+
}
16+
17+
//export FLBPluginInit
18+
func FLBPluginInit(plugin unsafe.Pointer) int {
19+
return output.FLB_OK
20+
}
21+
22+
//export FLBPluginFlushCtx
23+
func FLBPluginFlushCtx(ctx, data unsafe.Pointer, length C.int, tag *C.char) int {
24+
// Write to a stdout to verify it received data
25+
dec := output.NewDecoder(data, int(length))
26+
var logrecords []string
27+
for {
28+
ret, _, record := output.GetRecord(dec)
29+
if ret != 0 {
30+
break
31+
}
32+
logrecords = append(logrecords, fmt.Sprintf("%v", record))
33+
}
34+
for _, record := range logrecords {
35+
fmt.Printf("%s\n", record)
36+
}
37+
38+
return output.FLB_OK
39+
}
40+
41+
//export FLBPluginExit
42+
func FLBPluginExit() int {
43+
return output.FLB_OK
44+
}
45+
46+
func main() {
47+
}
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
/* Code generated by cmd/cgo; DO NOT EDIT. */
2+
3+
/* package command-line-arguments */
4+
5+
6+
#line 1 "cgo-builtin-export-prolog"
7+
8+
#include <stddef.h>
9+
10+
#ifndef GO_CGO_EXPORT_PROLOGUE_H
11+
#define GO_CGO_EXPORT_PROLOGUE_H
12+
13+
#ifndef GO_CGO_GOSTRING_TYPEDEF
14+
typedef struct { const char *p; ptrdiff_t n; } _GoString_;
15+
extern size_t _GoStringLen(_GoString_ s);
16+
extern const char *_GoStringPtr(_GoString_ s);
17+
#endif
18+
19+
#endif
20+
21+
/* Start of preamble from import "C" comments. */
22+
23+
24+
25+
26+
/* End of preamble from import "C" comments. */
27+
28+
29+
/* Start of boilerplate cgo prologue. */
30+
#line 1 "cgo-gcc-export-header-prolog"
31+
32+
#ifndef GO_CGO_PROLOGUE_H
33+
#define GO_CGO_PROLOGUE_H
34+
35+
typedef signed char GoInt8;
36+
typedef unsigned char GoUint8;
37+
typedef short GoInt16;
38+
typedef unsigned short GoUint16;
39+
typedef int GoInt32;
40+
typedef unsigned int GoUint32;
41+
typedef long long GoInt64;
42+
typedef unsigned long long GoUint64;
43+
typedef GoInt64 GoInt;
44+
typedef GoUint64 GoUint;
45+
typedef size_t GoUintptr;
46+
typedef float GoFloat32;
47+
typedef double GoFloat64;
48+
#ifdef _MSC_VER
49+
#if !defined(__cplusplus) || _MSVC_LANG <= 201402L
50+
#include <complex.h>
51+
typedef _Fcomplex GoComplex64;
52+
typedef _Dcomplex GoComplex128;
53+
#else
54+
#include <complex>
55+
typedef std::complex<float> GoComplex64;
56+
typedef std::complex<double> GoComplex128;
57+
#endif
58+
#else
59+
typedef float _Complex GoComplex64;
60+
typedef double _Complex GoComplex128;
61+
#endif
62+
63+
/*
64+
static assertion to make sure the file is being used on architecture
65+
at least with matching size of GoInt.
66+
*/
67+
typedef char _check_for_64_bit_pointer_matching_GoInt[sizeof(void*)==64/8 ? 1:-1];
68+
69+
#ifndef GO_CGO_GOSTRING_TYPEDEF
70+
typedef _GoString_ GoString;
71+
#endif
72+
typedef void *GoMap;
73+
typedef void *GoChan;
74+
typedef struct { void *t; void *v; } GoInterface;
75+
typedef struct { void *data; GoInt len; GoInt cap; } GoSlice;
76+
77+
#endif
78+
79+
/* End of boilerplate cgo prologue. */
80+
81+
#ifdef __cplusplus
82+
extern "C" {
83+
#endif
84+
85+
extern GoInt FLBPluginRegister(void* def);
86+
extern GoInt FLBPluginInit(void* plugin);
87+
extern GoInt FLBPluginFlushCtx(void* ctx, void* data, int length, char* tag);
88+
extern GoInt FLBPluginExit(void);
89+
90+
#ifdef __cplusplus
91+
}
92+
#endif
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
#!/bin/sh
2+
3+
# Setup environment if not already set
4+
if [ -z "$FLB_BIN" ]; then
5+
FLB_ROOT=${FLB_ROOT:-$(cd $(dirname $0)/../.. && pwd)}
6+
FLB_BIN=${FLB_BIN:-$FLB_ROOT/build/bin/fluent-bit}
7+
fi
8+
9+
echo "Using Fluent Bit at: $FLB_BIN"
10+
11+
. $FLB_RUNTIME_SHELL_PATH/go_plugins/build_test_plugins.sh
12+
13+
test_proxy_logs_compatibility() {
14+
export SIGNAL_FILE_PATH="/tmp/flb_signal_logs_$$.txt"
15+
STDOUT_OUTPUT_FILE="/tmp/test_logs_stdout_$$.txt"
16+
17+
rm -f "$STDOUT_OUTPUT_FILE" "$SIGNAL_FILE_PATH"
18+
19+
$FLB_BIN -e $FLB_ROOT/build/test_logs_go.so -c $FLB_RUNTIME_SHELL_CONF/proxy_logs_test.conf > "$STDOUT_OUTPUT_FILE" 2>&1 &
20+
FLB_PID=$!
21+
22+
sleep 3
23+
24+
if [ -f "$STDOUT_OUTPUT_FILE" ]; then
25+
echo "SUCCESS: Captured Fluent Bit output"
26+
echo "Output contents:"
27+
cat "$STDOUT_OUTPUT_FILE"
28+
else
29+
echo "FAIL: No stdout output captured"
30+
return 1
31+
fi
32+
33+
# Clean up
34+
rm -f "$STDOUT_OUTPUT_FILE" "$SIGNAL_FILE_PATH"
35+
}
36+
37+
# Load the runtime shell environment
38+
. $FLB_RUNTIME_SHELL_PATH/runtime_shell.env

0 commit comments

Comments
 (0)