update
This commit is contained in:
276
test/test_js_to_js_mix_payload_sender.js
Normal file
276
test/test_js_to_js_mix_payload_sender.js
Normal file
@@ -0,0 +1,276 @@
|
||||
#!/usr/bin/env node
|
||||
// Test script for mixed-content message testing
|
||||
// Tests sending a mix of text, json, table, image, audio, video, and binary data
|
||||
// from JavaScript serviceA to JavaScript serviceB using NATSBridge.js smartsend
|
||||
//
|
||||
// This test demonstrates that any combination and any number of mixed content
|
||||
// can be sent and received correctly.
|
||||
|
||||
const { smartsend, uuid4, log_trace, _serialize_data } = require('./src/NATSBridge');
|
||||
|
||||
// Configuration
|
||||
const SUBJECT = "/NATSBridge_mix_test";
|
||||
const NATS_URL = "nats.yiem.cc";
|
||||
const FILESERVER_URL = "http://192.168.88.104:8080";
|
||||
|
||||
// Create correlation ID for tracing
|
||||
const correlation_id = uuid4();
|
||||
|
||||
// Helper: Log with correlation ID
|
||||
function log_trace(message) {
|
||||
const timestamp = new Date().toISOString();
|
||||
console.log(`[${timestamp}] [Correlation: ${correlation_id}] ${message}`);
|
||||
}
|
||||
|
||||
// File upload handler for plik server
|
||||
async function plik_upload_handler(fileserver_url, dataname, data, correlation_id) {
|
||||
log_trace(correlation_id, `Uploading ${dataname} to fileserver: ${fileserver_url}`);
|
||||
|
||||
// Step 1: Get upload ID and token
|
||||
const url_getUploadID = `${fileserver_url}/upload`;
|
||||
const headers = {
|
||||
"Content-Type": "application/json"
|
||||
};
|
||||
const body = JSON.stringify({ OneShot: true });
|
||||
|
||||
let response = await fetch(url_getUploadID, {
|
||||
method: "POST",
|
||||
headers: headers,
|
||||
body: body
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(`Failed to get upload ID: ${response.status} ${response.statusText}`);
|
||||
}
|
||||
|
||||
const responseJson = await response.json();
|
||||
const uploadid = responseJson.id;
|
||||
const uploadtoken = responseJson.uploadToken;
|
||||
|
||||
// Step 2: Upload file data
|
||||
const url_upload = `${fileserver_url}/file/${uploadid}`;
|
||||
|
||||
// Create multipart form data
|
||||
const formData = new FormData();
|
||||
const blob = new Blob([data], { type: "application/octet-stream" });
|
||||
formData.append("file", blob, dataname);
|
||||
|
||||
response = await fetch(url_upload, {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"X-UploadToken": uploadtoken
|
||||
},
|
||||
body: formData
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(`Failed to upload file: ${response.status} ${response.statusText}`);
|
||||
}
|
||||
|
||||
const fileResponseJson = await response.json();
|
||||
const fileid = fileResponseJson.id;
|
||||
|
||||
// Build the download URL
|
||||
const url = `${fileserver_url}/file/${uploadid}/${fileid}/${encodeURIComponent(dataname)}`;
|
||||
|
||||
log_trace(correlation_id, `Uploaded to URL: ${url}`);
|
||||
|
||||
return {
|
||||
status: response.status,
|
||||
uploadid: uploadid,
|
||||
fileid: fileid,
|
||||
url: url
|
||||
};
|
||||
}
|
||||
|
||||
// Helper: Create sample data for each type
|
||||
function create_sample_data() {
|
||||
// Text data (small - direct transport)
|
||||
const text_data = "Hello! This is a test chat message. 🎉\nHow are you doing today? 😊";
|
||||
|
||||
// Dictionary/JSON data (medium - could be direct or link)
|
||||
const dict_data = {
|
||||
type: "chat",
|
||||
sender: "serviceA",
|
||||
receiver: "serviceB",
|
||||
metadata: {
|
||||
timestamp: new Date().toISOString(),
|
||||
priority: "high",
|
||||
tags: ["urgent", "chat", "test"]
|
||||
},
|
||||
content: {
|
||||
text: "This is a JSON-formatted chat message with nested structure.",
|
||||
format: "markdown",
|
||||
mentions: ["user1", "user2"]
|
||||
}
|
||||
};
|
||||
|
||||
// Table data (small - direct transport) - NOT IMPLEMENTED (requires apache-arrow)
|
||||
// const table_data_small = {...};
|
||||
|
||||
// Table data (large - link transport) - NOT IMPLEMENTED (requires apache-arrow)
|
||||
// const table_data_large = {...};
|
||||
|
||||
// Image data (small binary - direct transport)
|
||||
// Create a simple 10x10 pixel PNG-like data
|
||||
const image_width = 10;
|
||||
const image_height = 10;
|
||||
let image_data = new Uint8Array(128); // PNG header + pixel data
|
||||
// PNG header
|
||||
image_data[0] = 0x89;
|
||||
image_data[1] = 0x50;
|
||||
image_data[2] = 0x4E;
|
||||
image_data[3] = 0x47;
|
||||
image_data[4] = 0x0D;
|
||||
image_data[5] = 0x0A;
|
||||
image_data[6] = 0x1A;
|
||||
image_data[7] = 0x0A;
|
||||
// Simple RGB data (10*10*3 = 300 bytes)
|
||||
for (let i = 0; i < 300; i++) {
|
||||
image_data[i + 8] = 0xFF; // Red pixel
|
||||
}
|
||||
|
||||
// Image data (large - link transport)
|
||||
const large_image_width = 500;
|
||||
const large_image_height = 1000;
|
||||
const large_image_data = new Uint8Array(large_image_width * large_image_height * 3 + 8);
|
||||
// PNG header
|
||||
large_image_data[0] = 0x89;
|
||||
large_image_data[1] = 0x50;
|
||||
large_image_data[2] = 0x4E;
|
||||
large_image_data[3] = 0x47;
|
||||
large_image_data[4] = 0x0D;
|
||||
large_image_data[5] = 0x0A;
|
||||
large_image_data[6] = 0x1A;
|
||||
large_image_data[7] = 0x0A;
|
||||
// Random RGB data
|
||||
for (let i = 0; i < large_image_width * large_image_height * 3; i++) {
|
||||
large_image_data[i + 8] = Math.floor(Math.random() * 255);
|
||||
}
|
||||
|
||||
// Audio data (small binary - direct transport)
|
||||
const audio_data = new Uint8Array(100);
|
||||
for (let i = 0; i < 100; i++) {
|
||||
audio_data[i] = Math.floor(Math.random() * 255);
|
||||
}
|
||||
|
||||
// Audio data (large - link transport)
|
||||
const large_audio_data = new Uint8Array(1_500_000);
|
||||
for (let i = 0; i < 1_500_000; i++) {
|
||||
large_audio_data[i] = Math.floor(Math.random() * 255);
|
||||
}
|
||||
|
||||
// Video data (small binary - direct transport)
|
||||
const video_data = new Uint8Array(150);
|
||||
for (let i = 0; i < 150; i++) {
|
||||
video_data[i] = Math.floor(Math.random() * 255);
|
||||
}
|
||||
|
||||
// Video data (large - link transport)
|
||||
const large_video_data = new Uint8Array(1_500_000);
|
||||
for (let i = 0; i < 1_500_000; i++) {
|
||||
large_video_data[i] = Math.floor(Math.random() * 255);
|
||||
}
|
||||
|
||||
// Binary data (small - direct transport)
|
||||
const binary_data = new Uint8Array(200);
|
||||
for (let i = 0; i < 200; i++) {
|
||||
binary_data[i] = Math.floor(Math.random() * 255);
|
||||
}
|
||||
|
||||
// Binary data (large - link transport)
|
||||
const large_binary_data = new Uint8Array(1_500_000);
|
||||
for (let i = 0; i < 1_500_000; i++) {
|
||||
large_binary_data[i] = Math.floor(Math.random() * 255);
|
||||
}
|
||||
|
||||
return {
|
||||
text_data,
|
||||
dict_data,
|
||||
// table_data_small,
|
||||
// table_data_large,
|
||||
image_data,
|
||||
large_image_data,
|
||||
audio_data,
|
||||
large_audio_data,
|
||||
video_data,
|
||||
large_video_data,
|
||||
binary_data,
|
||||
large_binary_data
|
||||
};
|
||||
}
|
||||
|
||||
// Sender: Send mixed content via smartsend
|
||||
async function test_mix_send() {
|
||||
// Create sample data
|
||||
const { text_data, dict_data, image_data, large_image_data, audio_data, large_audio_data, video_data, large_video_data, binary_data, large_binary_data } = create_sample_data();
|
||||
|
||||
// Create payloads list - mixed content with both small and large data
|
||||
// Small data uses direct transport, large data uses link transport
|
||||
const payloads = [
|
||||
// Small data (direct transport) - text, dictionary
|
||||
{ dataname: "chat_text", data: text_data, type: "text" },
|
||||
{ dataname: "chat_json", data: dict_data, type: "dictionary" },
|
||||
// { dataname: "chat_table_small", data: table_data_small, type: "table" },
|
||||
|
||||
// Large data (link transport) - large image, large audio, large video, large binary
|
||||
// { dataname: "chat_table_large", data: table_data_large, type: "table" },
|
||||
{ dataname: "user_image_large", data: large_image_data, type: "image" },
|
||||
{ dataname: "audio_clip_large", data: large_audio_data, type: "audio" },
|
||||
{ dataname: "video_clip_large", data: large_video_data, type: "video" },
|
||||
{ dataname: "binary_file_large", data: large_binary_data, type: "binary" }
|
||||
];
|
||||
|
||||
// Use smartsend with mixed content
|
||||
const env = await smartsend(
|
||||
SUBJECT,
|
||||
payloads,
|
||||
{
|
||||
natsUrl: NATS_URL,
|
||||
fileserverUrl: FILESERVER_URL,
|
||||
fileserverUploadHandler: plik_upload_handler,
|
||||
sizeThreshold: 1_000_000,
|
||||
correlationId: correlation_id,
|
||||
msgPurpose: "chat",
|
||||
senderName: "mix_sender",
|
||||
receiverName: "",
|
||||
receiverId: "",
|
||||
replyTo: "",
|
||||
replyToMsgId: ""
|
||||
}
|
||||
);
|
||||
|
||||
log_trace(`Sent message with ${env.payloads.length} payloads`);
|
||||
|
||||
// Log transport type for each payload
|
||||
for (let i = 0; i < env.payloads.length; i++) {
|
||||
const payload = env.payloads[i];
|
||||
log_trace(`Payload ${i + 1} ('${payload.dataname}'):`);
|
||||
log_trace(` Transport: ${payload.transport}`);
|
||||
log_trace(` Type: ${payload.type}`);
|
||||
log_trace(` Size: ${payload.size} bytes`);
|
||||
log_trace(` Encoding: ${payload.encoding}`);
|
||||
|
||||
if (payload.transport === "link") {
|
||||
log_trace(` URL: ${payload.data}`);
|
||||
}
|
||||
}
|
||||
|
||||
// Summary
|
||||
console.log("\n--- Transport Summary ---");
|
||||
const direct_count = env.payloads.filter(p => p.transport === "direct").length;
|
||||
const link_count = env.payloads.filter(p => p.transport === "link").length;
|
||||
log_trace(`Direct transport: ${direct_count} payloads`);
|
||||
log_trace(`Link transport: ${link_count} payloads`);
|
||||
}
|
||||
|
||||
// Run the test
|
||||
console.log("Starting mixed-content transport test...");
|
||||
console.log(`Correlation ID: ${correlation_id}`);
|
||||
|
||||
// Run sender
|
||||
console.log("start smartsend for mixed content");
|
||||
test_mix_send();
|
||||
|
||||
console.log("\nTest completed.");
|
||||
console.log("Note: Run test_js_to_js_mix_receiver.js to receive the messages.");
|
||||
Reference in New Issue
Block a user