blob: 1be2e284493ead3ff0a8e6eac9cba6fbc76b2f91 [file]
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.
*/
import { Session } from "../../src/client/Session";
import { TSDataType } from "../../src/utils/DataTypes";
describe("Session E2E Tests", () => {
const IOTDB_HOST = process.env.IOTDB_HOST || "localhost";
const IOTDB_PORT = parseInt(process.env.IOTDB_PORT || "6667");
const IOTDB_USER = process.env.IOTDB_USER || "root";
const IOTDB_PASSWORD = process.env.IOTDB_PASSWORD || "root";
let session: Session;
beforeAll(async () => {
session = new Session({
host: IOTDB_HOST,
port: IOTDB_PORT,
username: IOTDB_USER,
password: IOTDB_PASSWORD,
});
try {
await session.open();
} catch (error) {
console.warn("Could not connect to IoTDB. E2E tests will be skipped.");
console.warn(
"Set IOTDB_HOST, IOTDB_PORT to run E2E tests against a real instance.",
);
try {
await session.close();
} catch {
// Ignore cleanup errors
}
}
}, 60000); // 30 second timeout for connection
afterAll(async () => {
if (session && session.isOpen()) {
// Cleanup test data
try {
await session.executeNonQueryStatement("DROP DATABASE root.test");
} catch (e) {
// Ignore cleanup errors
}
await session.close();
}
}, 60000);
test("Should open and close session", async () => {
if (!session.isOpen()) {
console.log("Skipping test - no IoTDB connection");
return;
}
expect(session.isOpen()).toBe(true);
}, 60000);
test("Should create database and timeseries (tree model)", async () => {
if (!session.isOpen()) {
console.log("Skipping test - no IoTDB connection");
return;
}
// Create database (storage group) - ignore if already exists
try {
await session.executeNonQueryStatement("CREATE DATABASE root.test");
} catch (e: any) {
if (!e.message?.includes("already")) {
throw e;
}
}
// Create timeseries - handle if they already exist
try {
await session.executeNonQueryStatement(
"CREATE TIMESERIES root.test.device1.status WITH DATATYPE=BOOLEAN, ENCODING=PLAIN",
);
} catch (e: any) {
// IoTDB returns "already exist" (without 's')
if (!e.message?.includes("already exist")) {
throw e;
}
}
try {
await session.executeNonQueryStatement(
"CREATE TIMESERIES root.test.device1.temperature WITH DATATYPE=FLOAT, ENCODING=RLE",
);
} catch (e: any) {
// IoTDB returns "already exist" (without 's')
if (!e.message?.includes("already exist")) {
throw e;
}
}
// Verify timeseries created
const dataSet = await session.executeQueryStatement(
"SHOW TIMESERIES root.test.**",
);
let rowCount = 0;
while (await dataSet.hasNext()) {
dataSet.next();
rowCount++;
}
await dataSet.close();
expect(rowCount).toBeGreaterThanOrEqual(2);
}, 60000);
test("Should execute query statement (SHOW DATABASES)", async () => {
if (!session.isOpen()) {
console.log("Skipping test - no IoTDB connection");
return;
}
const dataSet = await session.executeQueryStatement("SHOW DATABASES");
expect(dataSet).toBeDefined();
expect(dataSet.getColumnNames()).toBeDefined();
expect(Array.isArray(dataSet.getColumnNames())).toBe(true);
let rowCount = 0;
while (await dataSet.hasNext()) {
dataSet.next();
rowCount++;
}
await dataSet.close();
expect(rowCount).toBeGreaterThan(0);
}, 60000);
test("Should insert and query data (tree model)", async () => {
if (!session.isOpen()) {
console.log("Skipping test - no IoTDB connection");
return;
}
const now = Date.now();
// Insert tablet data
const tablet = {
deviceId: "root.test.device1",
measurements: ["status", "temperature"],
dataTypes: [TSDataType.BOOLEAN, TSDataType.FLOAT],
timestamps: [now, now + 1, now + 2],
values: [
[true, 20.5],
[false, 21.0],
[true, 21.5],
],
};
await session.insertTablet(tablet);
// Query the data
const dataSet = await session.executeQueryStatement(
"SELECT status, temperature FROM root.test.device1 LIMIT 5",
);
expect(dataSet).toBeDefined();
expect(dataSet.getColumnNames()).toBeDefined();
let rowCount = 0;
while (await dataSet.hasNext()) {
dataSet.next();
rowCount++;
}
await dataSet.close();
expect(rowCount).toBeGreaterThan(0);
}, 60000);
test("Should insert multiple tablets in single RPC call using insertTablets", async () => {
if (!session.isOpen()) {
console.log("Skipping test - no IoTDB connection");
return;
}
const baseTime = Date.now();
// Create multiple tablets for different devices
const tablets = [];
for (let i = 0; i < 5; i++) {
tablets.push({
deviceId: `root.test.batch_device${i}`,
measurements: ["temperature"],
dataTypes: [TSDataType.FLOAT],
timestamps: [baseTime + i * 1000],
values: [[25.5 + i]],
});
}
// Insert all tablets in single RPC call
await session.insertTablets(tablets);
// Verify data was inserted
const dataSet = await session.executeQueryStatement(
"SELECT * FROM root.test.batch_device0"
);
let rowCount = 0;
while (await dataSet.hasNext()) {
dataSet.next();
rowCount++;
}
await dataSet.close();
expect(rowCount).toBeGreaterThan(0);
}, 60000);
test("Should insert tablets concurrently using insertTabletsParallel", async () => {
if (!session.isOpen()) {
console.log("Skipping test - no IoTDB connection");
return;
}
const baseTime = Date.now();
// Create tablets
const tablets = [];
for (let i = 0; i < 10; i++) {
tablets.push({
deviceId: `root.test.parallel_batch${i}`,
measurements: ["humidity"],
dataTypes: [TSDataType.FLOAT],
timestamps: [baseTime + i * 1000],
values: [[60.0 + i]],
});
}
// Insert tablets concurrently (using single session, not pool)
await session.insertTabletsParallel(tablets, 5);
// Verify data was inserted
const dataSet = await session.executeQueryStatement(
"SELECT * FROM root.test.parallel_batch0"
);
let rowCount = 0;
while (await dataSet.hasNext()) {
dataSet.next();
rowCount++;
}
await dataSet.close();
expect(rowCount).toBeGreaterThan(0);
}, 60000);
});