From cf00cb6a3595caca6492cc8da803ec2112365a8f Mon Sep 17 00:00:00 2001 From: Serhii Mamedov Date: Tue, 23 Jun 2026 14:02:17 +0300 Subject: [PATCH 1/9] Fix unstable CI tests --- .github/workflows/ci.yml | 6 +++--- package.json | 1 + 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c3a7b95..a47c358 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -147,12 +147,12 @@ jobs: - name: Run unit tests (Node.js) if: matrix.runtime.kind == 'node' - run: npm run test:unit + run: npm run test:unit:sequential - name: Run unit tests (Bun) if: matrix.runtime.kind == 'bun' - run: bun x vitest --no-watch + run: bun x vitest --no-watch --no-file-parallelism --sequence.concurrent=false - name: Run unit tests (Deno) if: matrix.runtime.kind == 'deno' - run: deno run -A --node-modules-dir=auto npm:vitest --no-watch + run: deno run -A --node-modules-dir=auto npm:vitest --no-watch --no-file-parallelism --sequence.concurrent=false diff --git a/package.json b/package.json index cfc09da..3b44a6e 100644 --- a/package.json +++ b/package.json @@ -16,6 +16,7 @@ "build:ts": "rolldown -c rolldown.config.mjs", "build": "npm run clean && npm run build:native && npm run build:ts", "test:unit": "vitest --no-watch", + "test:unit:sequential": "vitest --no-watch --no-file-parallelism --sequence.concurrent=false", "test:unit:bun": "bun x vitest --no-watch", "test:unit:deno": "deno run -A --node-modules-dir=auto npm:vitest --no-watch", "test": "npm run test:unit", From 9cc0d78afeddc5fd436108e95b2594ada07ad1e6 Mon Sep 17 00:00:00 2001 From: Serhii Mamedov Date: Wed, 24 Jun 2026 14:45:07 +0300 Subject: [PATCH 2/9] fix: ensure proper cleanup of pipeline resources in destructor --- src/cpp/pipeline.cpp | 9 +++++++-- src/cpp/pipeline.hpp | 1 + 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/cpp/pipeline.cpp b/src/cpp/pipeline.cpp index 486bdf6..06b377f 100644 --- a/src/cpp/pipeline.cpp +++ b/src/cpp/pipeline.cpp @@ -106,6 +106,12 @@ Pipeline::Pipeline(const Napi::CallbackInfo &info) : ); } +Pipeline::~Pipeline() { + if (pipeline) { + gst_element_set_state(GST_ELEMENT(pipeline.get()), GST_STATE_NULL); + } +} + Napi::Value Pipeline::play(const Napi::CallbackInfo &info) { Napi::Env env = info.Env(); @@ -295,8 +301,7 @@ Napi::Value Pipeline::end_of_stream(const Napi::CallbackInfo &info) { } // Send EOS event to the pipeline - gboolean result = - gst_element_send_event(GST_ELEMENT(pipeline.get()), gst_event_new_eos()); + gboolean result = gst_element_send_event(GST_ELEMENT(pipeline.get()), gst_event_new_eos()); return Napi::Boolean::New(env, result); } diff --git a/src/cpp/pipeline.hpp b/src/cpp/pipeline.hpp index a976577..972b5f5 100644 --- a/src/cpp/pipeline.hpp +++ b/src/cpp/pipeline.hpp @@ -12,6 +12,7 @@ class Pipeline : public Napi::ObjectWrap { static Napi::Value ElementExists(const Napi::CallbackInfo &info); Pipeline(const Napi::CallbackInfo &info); + ~Pipeline(); Napi::Value play(const Napi::CallbackInfo &info); Napi::Value pause(const Napi::CallbackInfo &info); From a63537649bf1ddc30a9922a6db3ba757edef6723 Mon Sep 17 00:00:00 2001 From: Serhii Mamedov Date: Wed, 24 Jun 2026 15:26:45 +0300 Subject: [PATCH 3/9] Revert adding destructor --- src/cpp/pipeline.cpp | 6 ------ src/cpp/pipeline.hpp | 1 - 2 files changed, 7 deletions(-) diff --git a/src/cpp/pipeline.cpp b/src/cpp/pipeline.cpp index 06b377f..86a3791 100644 --- a/src/cpp/pipeline.cpp +++ b/src/cpp/pipeline.cpp @@ -106,12 +106,6 @@ Pipeline::Pipeline(const Napi::CallbackInfo &info) : ); } -Pipeline::~Pipeline() { - if (pipeline) { - gst_element_set_state(GST_ELEMENT(pipeline.get()), GST_STATE_NULL); - } -} - Napi::Value Pipeline::play(const Napi::CallbackInfo &info) { Napi::Env env = info.Env(); diff --git a/src/cpp/pipeline.hpp b/src/cpp/pipeline.hpp index 972b5f5..a976577 100644 --- a/src/cpp/pipeline.hpp +++ b/src/cpp/pipeline.hpp @@ -12,7 +12,6 @@ class Pipeline : public Napi::ObjectWrap { static Napi::Value ElementExists(const Napi::CallbackInfo &info); Pipeline(const Napi::CallbackInfo &info); - ~Pipeline(); Napi::Value play(const Napi::CallbackInfo &info); Napi::Value pause(const Napi::CallbackInfo &info); From abda828d0d5496f34c91f421f64227e0f4a45b66 Mon Sep 17 00:00:00 2001 From: Serhii Mamedov Date: Wed, 24 Jun 2026 15:27:50 +0300 Subject: [PATCH 4/9] Add timeouts to tests and remove file concurrency --- src/ts/appsink.test.ts | 17 +++++++++++------ src/ts/appsrc-eos.test.ts | 7 ++++++- src/ts/appsrc.test.ts | 2 +- src/ts/bus-pop.test.ts | 24 ++++++++++++++++-------- src/ts/codec.test.ts | 8 +++++--- src/ts/element-props.test.ts | 3 ++- src/ts/fakesink.test.ts | 13 ++++++++----- src/ts/pipeline-eos.test.ts | 5 ++++- src/ts/pipeline-pad.test.ts | 6 +++++- src/ts/pipeline-query.test.ts | 10 ++++++---- src/ts/pipeline-seek.test.ts | 6 +++++- src/ts/pipeline-state.test.ts | 13 ++++++++++++- src/ts/rtp-stats.test.ts | 10 ++++++---- 13 files changed, 87 insertions(+), 37 deletions(-) diff --git a/src/ts/appsink.test.ts b/src/ts/appsink.test.ts index 639e752..e5f8ff6 100644 --- a/src/ts/appsink.test.ts +++ b/src/ts/appsink.test.ts @@ -2,7 +2,7 @@ import { describe, expect, it } from "vitest"; import { Pipeline, type GStreamerSample } from "."; import { arePluginsAvailable } from "./test-utils"; -describe.concurrent("AppSink", () => { +describe("AppSink", () => { it("should pull frames", async () => { const pipeline = new Pipeline("videotestsrc ! videoconvert ! appsink name=sink"); const sink = pipeline.getElementByName("sink"); @@ -13,7 +13,8 @@ describe.concurrent("AppSink", () => { const result = await sink.getSample(); - pipeline.stop(); + await new Promise(resolve => setTimeout(resolve, 10)); + await pipeline.stop(); expect(result).not.toBeNull(); expect(result?.buffer).toBeDefined(); @@ -34,7 +35,8 @@ describe.concurrent("AppSink", () => { const result = await sink.getSample(10); - pipeline.stop(); + await new Promise(resolve => setTimeout(resolve, 10)); + await pipeline.stop(); expect(result).toBeNull(); } @@ -48,7 +50,8 @@ describe.concurrent("AppSink", () => { const result = await sink.getSample(); - pipeline.stop(); + await new Promise(resolve => setTimeout(resolve, 10)); + await pipeline.stop(); expect(result).toBeNull(); }); @@ -74,7 +77,8 @@ describe.concurrent("AppSink", () => { currFrames++; } - pipeline.stop(); + await new Promise(resolve => setTimeout(resolve, 10)); + await pipeline.stop(); expect(currFrames).toBe(frames); }); @@ -102,7 +106,8 @@ describe.concurrent("AppSink", () => { }); unsubscribe(); - pipeline.stop(); + await new Promise(resolve => setTimeout(resolve, 10)); + await pipeline.stop(); expect(samples).toHaveLength(frames); expect(samples[0].buffer).toBeDefined(); diff --git a/src/ts/appsrc-eos.test.ts b/src/ts/appsrc-eos.test.ts index 34ff4de..c8389b8 100644 --- a/src/ts/appsrc-eos.test.ts +++ b/src/ts/appsrc-eos.test.ts @@ -1,7 +1,7 @@ import { describe, expect, it } from "vitest"; import { Pipeline, type GstMessage } from "."; -describe.concurrent("AppSrc End-of-Stream", () => { +describe("AppSrc End-of-Stream", () => { it("should send EOS signal through endOfStream method", async () => { const pipeline = new Pipeline("appsrc name=source ! fakesink"); const source = pipeline.getElementByName("source"); @@ -44,6 +44,7 @@ describe.concurrent("AppSrc End-of-Stream", () => { } } + await new Promise(resolve => setTimeout(resolve, 10)); await pipeline.stop(); expect(eosReceived).toBe(true); @@ -64,6 +65,8 @@ describe.concurrent("AppSrc End-of-Stream", () => { }).toThrow(); } + await new Promise(resolve => setTimeout(resolve, 10)); + await pipeline.stop(); }); @@ -92,6 +95,8 @@ describe.concurrent("AppSrc End-of-Stream", () => { expect(error).toBeDefined(); } + await new Promise(resolve => setTimeout(resolve, 10)); + await pipeline.stop(); } }); diff --git a/src/ts/appsrc.test.ts b/src/ts/appsrc.test.ts index e41c25a..343f96f 100644 --- a/src/ts/appsrc.test.ts +++ b/src/ts/appsrc.test.ts @@ -1,7 +1,7 @@ import { describe, expect, it } from "vitest"; import { Pipeline } from "."; -describe.concurrent("AppSrc", () => { +describe("AppSrc", () => { it("should push buffer to app source", () => { const pipeline = new Pipeline("appsrc name=source ! fakesink"); const source = pipeline.getElementByName("source"); diff --git a/src/ts/bus-pop.test.ts b/src/ts/bus-pop.test.ts index 8b68b25..1d171a0 100644 --- a/src/ts/bus-pop.test.ts +++ b/src/ts/bus-pop.test.ts @@ -2,14 +2,15 @@ import { describe, expect, it } from "vitest"; import { Pipeline, type GstMessage } from "."; import { isWindows } from "./test-utils"; -describe.concurrent("Pipeline busPop Method", () => { +describe("Pipeline busPop Method", () => { it("should return null when no message available with timeout", async () => { const pipeline = new Pipeline("videotestsrc ! fakesink"); // Try to pop a message with a very short timeout (10ms) const message = await pipeline.busPop(10); - pipeline.stop(); + await new Promise(resolve => setTimeout(resolve, 10)); + await pipeline.stop(); // Should return null when timeout expires with no messages expect(message).toBeNull(); @@ -24,7 +25,8 @@ describe.concurrent("Pipeline busPop Method", () => { // Pop a message with reasonable timeout const message = await pipeline.busPop(1000); - pipeline.stop(); + await new Promise(resolve => setTimeout(resolve, 10)); + await pipeline.stop(); expect(message).not.toBeNull(); expect(typeof message?.type).toBe("string"); @@ -52,7 +54,8 @@ describe.concurrent("Pipeline busPop Method", () => { } } - pipeline.stop(); + await new Promise(resolve => setTimeout(resolve, 10)); + await pipeline.stop(); // Should have found at least one message during pipeline startup expect(foundMessage).toBe(true); @@ -66,7 +69,8 @@ describe.concurrent("Pipeline busPop Method", () => { const message = await pipeline.busPop(1000); - pipeline.stop(); + await new Promise(resolve => setTimeout(resolve, 10)); + await pipeline.stop(); if (message && message.type === "error") { expect(message.errorMessage).toBeDefined(); @@ -84,7 +88,8 @@ describe.concurrent("Pipeline busPop Method", () => { const endTime = Date.now(); const elapsed = endTime - startTime; - pipeline.stop(); + await new Promise(resolve => setTimeout(resolve, 10)); + await pipeline.stop(); // Should timeout within a reasonable range (timing varies by platform) expect(elapsed).toBeGreaterThan(80); @@ -101,7 +106,8 @@ describe.concurrent("Pipeline busPop Method", () => { // Use -1 for infinite timeout, but pipeline should generate EOS quickly const message = await pipeline.busPop(-1); - pipeline.stop(); + await new Promise(resolve => setTimeout(resolve, 10)); + await pipeline.stop(); // Should get a message (likely EOS or state-changed) expect(message).not.toBeNull(); @@ -127,7 +133,8 @@ describe.concurrent("Pipeline busPop Method", () => { } } - pipeline.stop(); + await new Promise(resolve => setTimeout(resolve, 10)); + await pipeline.stop(); if (messageWithStructure) { expect(messageWithStructure.structureName).toBeDefined(); @@ -149,6 +156,7 @@ describe.concurrent("Pipeline busPop Method", () => { message = await pipeline.busPop(); } while (message?.type !== "element" || message?.srcElementName !== "lev"); + await new Promise(resolve => setTimeout(resolve, 10)); await pipeline.stop(); expect(message?.peak).toBeInstanceOf(Array); diff --git a/src/ts/codec.test.ts b/src/ts/codec.test.ts index 1409d52..4ec4f63 100644 --- a/src/ts/codec.test.ts +++ b/src/ts/codec.test.ts @@ -2,7 +2,7 @@ import { describe, expect, it } from "vitest"; import { Pipeline, type GStreamerSample, GstBufferFlags, type BufferData } from "."; import { arePluginsAvailable } from "./test-utils"; -describe.concurrent("codec", () => { +describe("codec", () => { it.skipIf(!arePluginsAvailable(["x264enc", "rtph264pay", "rtph264depay", "h264parse"]))( "should be able to distinguish between delta and key frames", async () => { @@ -26,7 +26,8 @@ describe.concurrent("codec", () => { currFrames++; } - pipeline.stop(); + await new Promise(resolve => setTimeout(resolve, 10)); + await pipeline.stop(); const keyFrame = samples.find(e => e.flags ? !(e.flags & GstBufferFlags.GST_BUFFER_FLAG_DELTA_UNIT) : false @@ -60,7 +61,8 @@ describe.concurrent("codec", () => { }); unsubscribe(); - pipeline.stop(); + await new Promise(resolve => setTimeout(resolve, 10)); + await pipeline.stop(); expect(bufferData).toBeDefined(); expect(bufferData.buffer).toBeDefined(); diff --git a/src/ts/element-props.test.ts b/src/ts/element-props.test.ts index feaf345..bc11c8c 100644 --- a/src/ts/element-props.test.ts +++ b/src/ts/element-props.test.ts @@ -1,7 +1,7 @@ import { describe, it, expect } from "vitest"; import { Pipeline } from "./"; -describe.concurrent("Element Properties", () => { +describe("Element Properties", () => { it("should get prop value", async () => { const caps = "video/x-raw,format=(string)GRAY8"; const pipeline = new Pipeline(`videotestsrc ! capsfilter name=target caps=${caps} ! fakesink`); @@ -18,6 +18,7 @@ describe.concurrent("Element Properties", () => { expect(prop?.type).toBe("primitive"); caps.split(",").forEach(cap => expect(prop?.value).toContain(cap)); + await new Promise(resolve => setTimeout(resolve, 10)); await pipeline.stop(); }); diff --git a/src/ts/fakesink.test.ts b/src/ts/fakesink.test.ts index 1e902b5..7cb234c 100644 --- a/src/ts/fakesink.test.ts +++ b/src/ts/fakesink.test.ts @@ -1,7 +1,7 @@ import { describe, expect, it } from "vitest"; import { Pipeline, type GStreamerSample } from "."; -describe.concurrent("FakeSink", () => { +describe("FakeSink", () => { it("should capture last sample when enabled", async () => { const pipeline = new Pipeline("videotestsrc ! fakesink enable-last-sample=true name=sink"); const fakesink = pipeline.getElementByName("sink"); @@ -13,7 +13,8 @@ describe.concurrent("FakeSink", () => { // Get the last sample const sampleResult = fakesink.getElementProperty("last-sample"); - pipeline.stop(); + await new Promise(resolve => setTimeout(resolve, 10)); + await pipeline.stop(); expect(sampleResult).not.toBeNull(); expect(sampleResult?.type).toBe("sample"); @@ -45,7 +46,7 @@ describe.concurrent("FakeSink", () => { // Try to get the last sample (should be null since it's disabled) const sampleResult = fakesink.getElementProperty("last-sample"); - pipeline.stop(); + await pipeline.stop(); expect(sampleResult).toBeNull(); }); @@ -62,6 +63,7 @@ describe.concurrent("FakeSink", () => { await pipeline.play(); expect(pipeline.playing()).toBe(true); + await new Promise(resolve => setTimeout(resolve, 10)); await pipeline.stop(); expect(pipeline.playing()).toBe(false); }); @@ -82,7 +84,7 @@ describe.concurrent("FakeSink", () => { const sampleResult = fakesink.getElementProperty("last-sample"); - pipeline.stop(); + await pipeline.stop(); expect(sampleResult).not.toBeNull(); expect(sampleResult?.type).toBe("sample"); @@ -108,7 +110,8 @@ describe.concurrent("FakeSink", () => { const sampleResult = fakesink.getElementProperty("last-sample"); - pipeline.stop(); + await new Promise(resolve => setTimeout(resolve, 10)); + await pipeline.stop(); expect(sampleResult).not.toBeNull(); expect(sampleResult?.type).toBe("sample"); diff --git a/src/ts/pipeline-eos.test.ts b/src/ts/pipeline-eos.test.ts index 787bf06..a287edb 100644 --- a/src/ts/pipeline-eos.test.ts +++ b/src/ts/pipeline-eos.test.ts @@ -1,7 +1,7 @@ import { describe, expect, it } from "vitest"; import { Pipeline, type GstMessage } from "."; -describe.concurrent("Pipeline EOS - State-Gated Dispatch", () => { +describe("Pipeline EOS - State-Gated Dispatch", () => { it("should return true when pipeline is in PLAYING state", async () => { const pipeline = new Pipeline("videotestsrc ! fakesink"); @@ -53,6 +53,7 @@ describe.concurrent("Pipeline EOS - State-Gated Dispatch", () => { } } + await new Promise(resolve => setTimeout(resolve, 10)); await pipeline.stop(); expect(eosMessage).not.toBeNull(); @@ -72,6 +73,7 @@ describe.concurrent("Pipeline EOS - State-Gated Dispatch", () => { expect(result2).toBe(true); expect(result3).toBe(true); + await new Promise(resolve => setTimeout(resolve, 10)); await pipeline.stop(); }); @@ -83,6 +85,7 @@ describe.concurrent("Pipeline EOS - State-Gated Dispatch", () => { const resultWhilePlaying = pipeline.endOfStream(); expect(resultWhilePlaying).toBe(true); + await new Promise(resolve => setTimeout(resolve, 10)); await pipeline.stop(); const resultAfterStop = pipeline.endOfStream(); diff --git a/src/ts/pipeline-pad.test.ts b/src/ts/pipeline-pad.test.ts index 95411a2..70eea58 100644 --- a/src/ts/pipeline-pad.test.ts +++ b/src/ts/pipeline-pad.test.ts @@ -1,7 +1,7 @@ import { describe, it, expect } from "vitest"; import { Pipeline } from "./"; -describe.concurrent("Pipeline Pad Methods", () => { +describe("Pipeline Pad Methods", () => { it("should get pad information from an element", () => { const pipeline = new Pipeline("videotestsrc name=source ! fakesink name=sink"); const element = pipeline.getElementByName("source"); @@ -57,6 +57,9 @@ describe.concurrent("Pipeline Pad Methods", () => { expect(() => sel.setPad("active-pad", "sink_0")).not.toThrow(); expect(() => sel.setPad("active-pad", "sink_1")).not.toThrow(); expect(() => sel.setPad("active-pad", "sink_0")).not.toThrow(); + + await new Promise(resolve => setTimeout(resolve, 10)); + await pipeline.stop(); }); it("should throw error for setPad with invalid element", () => { @@ -124,6 +127,7 @@ describe.concurrent("Pipeline Pad Methods", () => { expect(srcPad.caps).toContain("height=(int)480"); } + await new Promise(resolve => setTimeout(resolve, 10)); await pipeline.stop(); }); }); diff --git a/src/ts/pipeline-query.test.ts b/src/ts/pipeline-query.test.ts index 22542f5..90ede9a 100644 --- a/src/ts/pipeline-query.test.ts +++ b/src/ts/pipeline-query.test.ts @@ -1,7 +1,7 @@ import { describe, expect, it } from "vitest"; import { Pipeline } from "."; -describe.concurrent("Pipeline Query Methods", () => { +describe("Pipeline Query Methods", () => { it("should query position from videotestsrc pipeline", async () => { const pipeline = new Pipeline("videotestsrc num-buffers=100 ! fakesink"); @@ -9,7 +9,8 @@ describe.concurrent("Pipeline Query Methods", () => { const position = pipeline.queryPosition(); - pipeline.stop(); + await new Promise(resolve => setTimeout(resolve, 10)); + await pipeline.stop(); // Position should be a number (could be -1 if not available) expect(typeof position).toBe("number"); @@ -22,7 +23,8 @@ describe.concurrent("Pipeline Query Methods", () => { const duration = pipeline.queryDuration(); - pipeline.stop(); + await new Promise(resolve => setTimeout(resolve, 10)); + await pipeline.stop(); // Duration should be a number (could be -1 if not available) expect(typeof duration).toBe("number"); @@ -54,7 +56,7 @@ describe.concurrent("Pipeline Query Methods", () => { const position2 = pipeline.queryPosition(); - pipeline.stop(); + await pipeline.stop(); expect(typeof position1).toBe("number"); expect(typeof position2).toBe("number"); diff --git a/src/ts/pipeline-seek.test.ts b/src/ts/pipeline-seek.test.ts index ab9e181..8b7fbe3 100644 --- a/src/ts/pipeline-seek.test.ts +++ b/src/ts/pipeline-seek.test.ts @@ -2,7 +2,7 @@ import { describe, expect, it } from "vitest"; import { Pipeline } from "."; import { isWindows } from "./test-utils"; -describe.concurrent("Pipeline Seek Method", () => { +describe("Pipeline Seek Method", () => { it("should seek to a specific position in a video pipeline", async () => { const pipeline = new Pipeline( "videotestsrc num-buffers=300 ! video/x-raw,framerate=30/1 ! fakesink" @@ -28,6 +28,7 @@ describe.concurrent("Pipeline Seek Method", () => { console.warn("Position query returned -1, this is known Windows behavior"); } + await new Promise(resolve => setTimeout(resolve, 10)); await pipeline.stop(); }); @@ -53,6 +54,7 @@ describe.concurrent("Pipeline Seek Method", () => { console.warn("Position query returned -1, this is known Windows behavior"); } + await new Promise(resolve => setTimeout(resolve, 10)); await pipeline.stop(); }); @@ -153,6 +155,7 @@ describe.concurrent("Pipeline Seek Method", () => { expect(position).toBeLessThan(2.2); } + await new Promise(resolve => setTimeout(resolve, 10)); await pipeline.stop(); }); @@ -190,6 +193,7 @@ describe.concurrent("Pipeline Seek Method", () => { expect(typeof position).toBe("number"); } + await new Promise(resolve => setTimeout(resolve, 10)); await pipeline.stop(); }); diff --git a/src/ts/pipeline-state.test.ts b/src/ts/pipeline-state.test.ts index 9a54a4a..5ac1cc0 100644 --- a/src/ts/pipeline-state.test.ts +++ b/src/ts/pipeline-state.test.ts @@ -1,7 +1,7 @@ import { describe, expect, it } from "vitest"; import { Pipeline } from "."; -describe.concurrent("Pipeline State Management", () => { +describe("Pipeline State Management", () => { it("should play a pipeline", async () => { const pipeline = new Pipeline("videotestsrc ! fakesink"); @@ -10,6 +10,7 @@ describe.concurrent("Pipeline State Management", () => { // Check that the pipeline is playing expect(pipeline.playing()).toBe(true); + await new Promise(resolve => setTimeout(resolve, 10)); await pipeline.stop(); }); @@ -24,6 +25,7 @@ describe.concurrent("Pipeline State Management", () => { // After pausing, pipeline should not be in playing state expect(pipeline.playing()).toBe(false); + await new Promise(resolve => setTimeout(resolve, 10)); await pipeline.stop(); }); @@ -33,6 +35,7 @@ describe.concurrent("Pipeline State Management", () => { await pipeline.play(); expect(pipeline.playing()).toBe(true); + await new Promise(resolve => setTimeout(resolve, 10)); await pipeline.stop(); // After stopping, pipeline should not be playing @@ -54,6 +57,7 @@ describe.concurrent("Pipeline State Management", () => { await pipeline.play(); expect(pipeline.playing()).toBe(true); + await new Promise(resolve => setTimeout(resolve, 10)); await pipeline.stop(); }); @@ -67,6 +71,7 @@ describe.concurrent("Pipeline State Management", () => { await pipeline.pause(); expect(pipeline.playing()).toBe(false); + await new Promise(resolve => setTimeout(resolve, 10)); await pipeline.stop(); }); @@ -89,6 +94,7 @@ describe.concurrent("Pipeline State Management", () => { await pipeline.play(); // play again (should be safe) expect(pipeline.playing()).toBe(true); + await new Promise(resolve => setTimeout(resolve, 10)); await pipeline.stop(); expect(pipeline.playing()).toBe(false); @@ -127,6 +133,9 @@ describe.concurrent("Pipeline State Management", () => { expect(positionWhilePlaying).toBeGreaterThan(0); expect(positionWhilePaused).toBeGreaterThanOrEqual(0); expect(positionAfterResume).toBeGreaterThan(0); + + await new Promise(resolve => setTimeout(resolve, 10)); + await pipeline.stop(); }); it("should provide detailed state change information", async () => { @@ -149,6 +158,8 @@ describe.concurrent("Pipeline State Management", () => { expect(stopResult.result).toBe("success"); expect(stopResult.targetState).toBe(1); // GST_STATE_NULL expect(stopResult.finalState).toBe(1); + + await new Promise(resolve => setTimeout(resolve, 10)); }); it("should accept timeout in milliseconds", async () => { diff --git a/src/ts/rtp-stats.test.ts b/src/ts/rtp-stats.test.ts index 013c544..9b3c160 100644 --- a/src/ts/rtp-stats.test.ts +++ b/src/ts/rtp-stats.test.ts @@ -2,7 +2,7 @@ import { describe, expect, it } from "vitest"; import { Pipeline, type BufferData } from "."; import { arePluginsAvailable } from "./test-utils"; -describe.concurrent("RTP Statistics", () => { +describe("RTP Statistics", () => { it.skipIf(!arePluginsAvailable(["x264enc", "rtph264pay", "rtph264depay", "h264parse"]))( "should extract RTP stats from rtph264depay stats property", async () => { @@ -18,7 +18,8 @@ describe.concurrent("RTP Statistics", () => { const statsResult = depayloader.getElementProperty("stats"); - pipeline.stop(); + await new Promise(resolve => setTimeout(resolve, 10)); + await pipeline.stop(); expect(statsResult).toBeDefined(); expect(statsResult).not.toBeNull(); @@ -76,7 +77,7 @@ describe.concurrent("RTP Statistics", () => { const statsResult = depayloader.getElementProperty("stats"); - pipeline.stop(); + await pipeline.stop(); // Verify pad probe captured RTP data expect(padProbeRtpData).toBeDefined(); @@ -101,7 +102,8 @@ describe.concurrent("RTP Statistics", () => { const statsResult = sink.getElementProperty("stats"); - pipeline.stop(); + await new Promise(resolve => setTimeout(resolve, 10)); + await pipeline.stop(); // fakesink has stats but different type (basesink stats, not RTP depayload stats) expect(statsResult).toBeDefined(); From f0a793b9db57c27615bea9252b59ee863debd6a9 Mon Sep 17 00:00:00 2001 From: Serhii Mamedov Date: Wed, 24 Jun 2026 15:39:25 +0300 Subject: [PATCH 5/9] Make tests sequential by default --- .github/workflows/ci.yml | 2 +- README.md | 5 ++--- package.json | 7 +++---- 3 files changed, 6 insertions(+), 8 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a47c358..1396715 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -147,7 +147,7 @@ jobs: - name: Run unit tests (Node.js) if: matrix.runtime.kind == 'node' - run: npm run test:unit:sequential + run: npm run test:unit - name: Run unit tests (Bun) if: matrix.runtime.kind == 'bun' diff --git a/README.md b/README.md index a010f6a..1605928 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,7 @@ This project represents a complete modernization of the old [node-gstreamer-supe - **Rolldown bundling**: Generates both CommonJS and ESM modules for maximum compatibility - **TypeScript-first**: Complete TypeScript support with full type definitions - **GYP build system**: Robust C++ compilation with proper dependency management -- **Modern testing**: Uses Vitest for fast, concurrent testing instead of legacy test frameworks +- **Modern testing**: Uses Vitest for fast testing instead of legacy test frameworks ### Enhanced Developer Experience @@ -1046,7 +1046,7 @@ if (sampleResult?.type === "sample") { ### Testing & Quality -- **Vitest**: Modern, fast test runner with concurrent execution +- **Vitest**: Modern, fast test runner - **Oxlint**: Fast Rust-based linter with TypeScript support - **Prettier**: Code formatting - **Coverage**: Built-in test coverage reporting @@ -1093,7 +1093,6 @@ gst-kit/ ## Performance Considerations -- **Concurrent Testing**: All tests run concurrently for faster execution - **Efficient Memory Management**: Proper buffer lifecycle management - **Async Operations**: Non-blocking operations for better performance - **Type Safety**: Compile-time error detection reduces runtime overhead diff --git a/package.json b/package.json index 3b44a6e..e40de26 100644 --- a/package.json +++ b/package.json @@ -15,10 +15,9 @@ "build:native": "node-gyp rebuild", "build:ts": "rolldown -c rolldown.config.mjs", "build": "npm run clean && npm run build:native && npm run build:ts", - "test:unit": "vitest --no-watch", - "test:unit:sequential": "vitest --no-watch --no-file-parallelism --sequence.concurrent=false", - "test:unit:bun": "bun x vitest --no-watch", - "test:unit:deno": "deno run -A --node-modules-dir=auto npm:vitest --no-watch", + "test:unit": "vitest --no-watch --no-file-parallelism --sequence.concurrent=false", + "test:unit:bun": "bun x vitest --no-watch --no-file-parallelism --sequence.concurrent=false", + "test:unit:deno": "deno run -A --node-modules-dir=auto npm:vitest --no-watch --no-file-parallelism --sequence.concurrent=false", "test": "npm run test:unit", "prepublishOnly": "npm run build:ts", "postinstall": "node scripts/ensure-native-addon.mjs", From c5189df92f8f4f3267e21a01a4966a4017c418c5 Mon Sep 17 00:00:00 2001 From: Serhii Mamedov Date: Wed, 24 Jun 2026 15:53:20 +0300 Subject: [PATCH 6/9] Increase slowTestThreshold --- vitest.config.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vitest.config.ts b/vitest.config.ts index 34590cc..d9c07f4 100644 --- a/vitest.config.ts +++ b/vitest.config.ts @@ -10,7 +10,7 @@ export default defineConfig({ reporter: ["text", "json", "html"], exclude: ["node_modules/", "dist/"], }, - slowTestThreshold: 2000, + slowTestThreshold: 5000, testTimeout: 20000, env: { NODE_ENV: "test", From 352b0758cdcd7bf5c3159d08f522c3035066c71d Mon Sep 17 00:00:00 2001 From: Serhii Mamedov Date: Wed, 24 Jun 2026 15:53:49 +0300 Subject: [PATCH 7/9] Remove unnecessary pipeline start --- src/ts/element-props.test.ts | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/ts/element-props.test.ts b/src/ts/element-props.test.ts index bc11c8c..3f7a9b8 100644 --- a/src/ts/element-props.test.ts +++ b/src/ts/element-props.test.ts @@ -6,8 +6,6 @@ describe("Element Properties", () => { const caps = "video/x-raw,format=(string)GRAY8"; const pipeline = new Pipeline(`videotestsrc ! capsfilter name=target caps=${caps} ! fakesink`); - await pipeline.play(); - const element = pipeline.getElementByName("target"); if (!element) throw new Error("Element not found"); @@ -17,9 +15,6 @@ describe("Element Properties", () => { expect(prop).not.toBeNull(); expect(prop?.type).toBe("primitive"); caps.split(",").forEach(cap => expect(prop?.value).toContain(cap)); - - await new Promise(resolve => setTimeout(resolve, 10)); - await pipeline.stop(); }); it("should set string property", () => { From 2ed02b493f9cc93a032806c19fb41cf116bc652a Mon Sep 17 00:00:00 2001 From: Serhii Mamedov Date: Wed, 24 Jun 2026 17:48:16 +0300 Subject: [PATCH 8/9] Remove hacky sleep statements --- src/ts/appsink.test.ts | 5 ----- src/ts/appsrc-eos.test.ts | 5 ----- src/ts/bus-pop.test.ts | 8 -------- src/ts/codec.test.ts | 2 -- src/ts/fakesink.test.ts | 3 --- src/ts/pipeline-eos.test.ts | 15 ++++++++++++--- src/ts/pipeline-pad.test.ts | 2 -- src/ts/pipeline-query.test.ts | 2 -- src/ts/pipeline-seek.test.ts | 4 ---- src/ts/pipeline-state.test.ts | 9 --------- src/ts/rtp-stats.test.ts | 2 -- 11 files changed, 12 insertions(+), 45 deletions(-) diff --git a/src/ts/appsink.test.ts b/src/ts/appsink.test.ts index e5f8ff6..1ca8f88 100644 --- a/src/ts/appsink.test.ts +++ b/src/ts/appsink.test.ts @@ -13,7 +13,6 @@ describe("AppSink", () => { const result = await sink.getSample(); - await new Promise(resolve => setTimeout(resolve, 10)); await pipeline.stop(); expect(result).not.toBeNull(); @@ -35,7 +34,6 @@ describe("AppSink", () => { const result = await sink.getSample(10); - await new Promise(resolve => setTimeout(resolve, 10)); await pipeline.stop(); expect(result).toBeNull(); @@ -50,7 +48,6 @@ describe("AppSink", () => { const result = await sink.getSample(); - await new Promise(resolve => setTimeout(resolve, 10)); await pipeline.stop(); expect(result).toBeNull(); @@ -77,7 +74,6 @@ describe("AppSink", () => { currFrames++; } - await new Promise(resolve => setTimeout(resolve, 10)); await pipeline.stop(); expect(currFrames).toBe(frames); @@ -106,7 +102,6 @@ describe("AppSink", () => { }); unsubscribe(); - await new Promise(resolve => setTimeout(resolve, 10)); await pipeline.stop(); expect(samples).toHaveLength(frames); diff --git a/src/ts/appsrc-eos.test.ts b/src/ts/appsrc-eos.test.ts index c8389b8..b29547a 100644 --- a/src/ts/appsrc-eos.test.ts +++ b/src/ts/appsrc-eos.test.ts @@ -44,7 +44,6 @@ describe("AppSrc End-of-Stream", () => { } } - await new Promise(resolve => setTimeout(resolve, 10)); await pipeline.stop(); expect(eosReceived).toBe(true); @@ -65,8 +64,6 @@ describe("AppSrc End-of-Stream", () => { }).toThrow(); } - await new Promise(resolve => setTimeout(resolve, 10)); - await pipeline.stop(); }); @@ -95,8 +92,6 @@ describe("AppSrc End-of-Stream", () => { expect(error).toBeDefined(); } - await new Promise(resolve => setTimeout(resolve, 10)); - await pipeline.stop(); } }); diff --git a/src/ts/bus-pop.test.ts b/src/ts/bus-pop.test.ts index 1d171a0..667728a 100644 --- a/src/ts/bus-pop.test.ts +++ b/src/ts/bus-pop.test.ts @@ -9,7 +9,6 @@ describe("Pipeline busPop Method", () => { // Try to pop a message with a very short timeout (10ms) const message = await pipeline.busPop(10); - await new Promise(resolve => setTimeout(resolve, 10)); await pipeline.stop(); // Should return null when timeout expires with no messages @@ -25,7 +24,6 @@ describe("Pipeline busPop Method", () => { // Pop a message with reasonable timeout const message = await pipeline.busPop(1000); - await new Promise(resolve => setTimeout(resolve, 10)); await pipeline.stop(); expect(message).not.toBeNull(); @@ -54,7 +52,6 @@ describe("Pipeline busPop Method", () => { } } - await new Promise(resolve => setTimeout(resolve, 10)); await pipeline.stop(); // Should have found at least one message during pipeline startup @@ -69,7 +66,6 @@ describe("Pipeline busPop Method", () => { const message = await pipeline.busPop(1000); - await new Promise(resolve => setTimeout(resolve, 10)); await pipeline.stop(); if (message && message.type === "error") { @@ -88,7 +84,6 @@ describe("Pipeline busPop Method", () => { const endTime = Date.now(); const elapsed = endTime - startTime; - await new Promise(resolve => setTimeout(resolve, 10)); await pipeline.stop(); // Should timeout within a reasonable range (timing varies by platform) @@ -106,7 +101,6 @@ describe("Pipeline busPop Method", () => { // Use -1 for infinite timeout, but pipeline should generate EOS quickly const message = await pipeline.busPop(-1); - await new Promise(resolve => setTimeout(resolve, 10)); await pipeline.stop(); // Should get a message (likely EOS or state-changed) @@ -133,7 +127,6 @@ describe("Pipeline busPop Method", () => { } } - await new Promise(resolve => setTimeout(resolve, 10)); await pipeline.stop(); if (messageWithStructure) { @@ -156,7 +149,6 @@ describe("Pipeline busPop Method", () => { message = await pipeline.busPop(); } while (message?.type !== "element" || message?.srcElementName !== "lev"); - await new Promise(resolve => setTimeout(resolve, 10)); await pipeline.stop(); expect(message?.peak).toBeInstanceOf(Array); diff --git a/src/ts/codec.test.ts b/src/ts/codec.test.ts index 4ec4f63..f1fc568 100644 --- a/src/ts/codec.test.ts +++ b/src/ts/codec.test.ts @@ -26,7 +26,6 @@ describe("codec", () => { currFrames++; } - await new Promise(resolve => setTimeout(resolve, 10)); await pipeline.stop(); const keyFrame = samples.find(e => @@ -61,7 +60,6 @@ describe("codec", () => { }); unsubscribe(); - await new Promise(resolve => setTimeout(resolve, 10)); await pipeline.stop(); expect(bufferData).toBeDefined(); diff --git a/src/ts/fakesink.test.ts b/src/ts/fakesink.test.ts index 7cb234c..8b9f2e0 100644 --- a/src/ts/fakesink.test.ts +++ b/src/ts/fakesink.test.ts @@ -13,7 +13,6 @@ describe("FakeSink", () => { // Get the last sample const sampleResult = fakesink.getElementProperty("last-sample"); - await new Promise(resolve => setTimeout(resolve, 10)); await pipeline.stop(); expect(sampleResult).not.toBeNull(); @@ -63,7 +62,6 @@ describe("FakeSink", () => { await pipeline.play(); expect(pipeline.playing()).toBe(true); - await new Promise(resolve => setTimeout(resolve, 10)); await pipeline.stop(); expect(pipeline.playing()).toBe(false); }); @@ -110,7 +108,6 @@ describe("FakeSink", () => { const sampleResult = fakesink.getElementProperty("last-sample"); - await new Promise(resolve => setTimeout(resolve, 10)); await pipeline.stop(); expect(sampleResult).not.toBeNull(); diff --git a/src/ts/pipeline-eos.test.ts b/src/ts/pipeline-eos.test.ts index a287edb..a344f4a 100644 --- a/src/ts/pipeline-eos.test.ts +++ b/src/ts/pipeline-eos.test.ts @@ -10,6 +10,8 @@ describe("Pipeline EOS - State-Gated Dispatch", () => { const result = pipeline.endOfStream(); expect(result).toBe(true); + await new Promise(resolve => setTimeout(resolve, 30)); + await pipeline.stop(); }); @@ -21,6 +23,8 @@ describe("Pipeline EOS - State-Gated Dispatch", () => { const result = pipeline.endOfStream(); expect(result).toBe(true); + await new Promise(resolve => setTimeout(resolve, 30)); + await pipeline.stop(); }); @@ -30,6 +34,8 @@ describe("Pipeline EOS - State-Gated Dispatch", () => { const result = pipeline.endOfStream(); expect(result).toBe(false); + await new Promise(resolve => setTimeout(resolve, 30)); + await pipeline.stop(); }); @@ -53,7 +59,8 @@ describe("Pipeline EOS - State-Gated Dispatch", () => { } } - await new Promise(resolve => setTimeout(resolve, 10)); + await new Promise(resolve => setTimeout(resolve, 30)); + await pipeline.stop(); expect(eosMessage).not.toBeNull(); @@ -73,7 +80,8 @@ describe("Pipeline EOS - State-Gated Dispatch", () => { expect(result2).toBe(true); expect(result3).toBe(true); - await new Promise(resolve => setTimeout(resolve, 10)); + await new Promise(resolve => setTimeout(resolve, 30)); + await pipeline.stop(); }); @@ -85,7 +93,8 @@ describe("Pipeline EOS - State-Gated Dispatch", () => { const resultWhilePlaying = pipeline.endOfStream(); expect(resultWhilePlaying).toBe(true); - await new Promise(resolve => setTimeout(resolve, 10)); + await new Promise(resolve => setTimeout(resolve, 30)); + await pipeline.stop(); const resultAfterStop = pipeline.endOfStream(); diff --git a/src/ts/pipeline-pad.test.ts b/src/ts/pipeline-pad.test.ts index 70eea58..814fc2e 100644 --- a/src/ts/pipeline-pad.test.ts +++ b/src/ts/pipeline-pad.test.ts @@ -58,7 +58,6 @@ describe("Pipeline Pad Methods", () => { expect(() => sel.setPad("active-pad", "sink_1")).not.toThrow(); expect(() => sel.setPad("active-pad", "sink_0")).not.toThrow(); - await new Promise(resolve => setTimeout(resolve, 10)); await pipeline.stop(); }); @@ -127,7 +126,6 @@ describe("Pipeline Pad Methods", () => { expect(srcPad.caps).toContain("height=(int)480"); } - await new Promise(resolve => setTimeout(resolve, 10)); await pipeline.stop(); }); }); diff --git a/src/ts/pipeline-query.test.ts b/src/ts/pipeline-query.test.ts index 90ede9a..8fb1c03 100644 --- a/src/ts/pipeline-query.test.ts +++ b/src/ts/pipeline-query.test.ts @@ -9,7 +9,6 @@ describe("Pipeline Query Methods", () => { const position = pipeline.queryPosition(); - await new Promise(resolve => setTimeout(resolve, 10)); await pipeline.stop(); // Position should be a number (could be -1 if not available) @@ -23,7 +22,6 @@ describe("Pipeline Query Methods", () => { const duration = pipeline.queryDuration(); - await new Promise(resolve => setTimeout(resolve, 10)); await pipeline.stop(); // Duration should be a number (could be -1 if not available) diff --git a/src/ts/pipeline-seek.test.ts b/src/ts/pipeline-seek.test.ts index 8b7fbe3..d198eff 100644 --- a/src/ts/pipeline-seek.test.ts +++ b/src/ts/pipeline-seek.test.ts @@ -28,7 +28,6 @@ describe("Pipeline Seek Method", () => { console.warn("Position query returned -1, this is known Windows behavior"); } - await new Promise(resolve => setTimeout(resolve, 10)); await pipeline.stop(); }); @@ -54,7 +53,6 @@ describe("Pipeline Seek Method", () => { console.warn("Position query returned -1, this is known Windows behavior"); } - await new Promise(resolve => setTimeout(resolve, 10)); await pipeline.stop(); }); @@ -155,7 +153,6 @@ describe("Pipeline Seek Method", () => { expect(position).toBeLessThan(2.2); } - await new Promise(resolve => setTimeout(resolve, 10)); await pipeline.stop(); }); @@ -193,7 +190,6 @@ describe("Pipeline Seek Method", () => { expect(typeof position).toBe("number"); } - await new Promise(resolve => setTimeout(resolve, 10)); await pipeline.stop(); }); diff --git a/src/ts/pipeline-state.test.ts b/src/ts/pipeline-state.test.ts index 5ac1cc0..41fa102 100644 --- a/src/ts/pipeline-state.test.ts +++ b/src/ts/pipeline-state.test.ts @@ -10,7 +10,6 @@ describe("Pipeline State Management", () => { // Check that the pipeline is playing expect(pipeline.playing()).toBe(true); - await new Promise(resolve => setTimeout(resolve, 10)); await pipeline.stop(); }); @@ -25,7 +24,6 @@ describe("Pipeline State Management", () => { // After pausing, pipeline should not be in playing state expect(pipeline.playing()).toBe(false); - await new Promise(resolve => setTimeout(resolve, 10)); await pipeline.stop(); }); @@ -35,7 +33,6 @@ describe("Pipeline State Management", () => { await pipeline.play(); expect(pipeline.playing()).toBe(true); - await new Promise(resolve => setTimeout(resolve, 10)); await pipeline.stop(); // After stopping, pipeline should not be playing @@ -57,7 +54,6 @@ describe("Pipeline State Management", () => { await pipeline.play(); expect(pipeline.playing()).toBe(true); - await new Promise(resolve => setTimeout(resolve, 10)); await pipeline.stop(); }); @@ -71,7 +67,6 @@ describe("Pipeline State Management", () => { await pipeline.pause(); expect(pipeline.playing()).toBe(false); - await new Promise(resolve => setTimeout(resolve, 10)); await pipeline.stop(); }); @@ -94,7 +89,6 @@ describe("Pipeline State Management", () => { await pipeline.play(); // play again (should be safe) expect(pipeline.playing()).toBe(true); - await new Promise(resolve => setTimeout(resolve, 10)); await pipeline.stop(); expect(pipeline.playing()).toBe(false); @@ -134,7 +128,6 @@ describe("Pipeline State Management", () => { expect(positionWhilePaused).toBeGreaterThanOrEqual(0); expect(positionAfterResume).toBeGreaterThan(0); - await new Promise(resolve => setTimeout(resolve, 10)); await pipeline.stop(); }); @@ -158,8 +151,6 @@ describe("Pipeline State Management", () => { expect(stopResult.result).toBe("success"); expect(stopResult.targetState).toBe(1); // GST_STATE_NULL expect(stopResult.finalState).toBe(1); - - await new Promise(resolve => setTimeout(resolve, 10)); }); it("should accept timeout in milliseconds", async () => { diff --git a/src/ts/rtp-stats.test.ts b/src/ts/rtp-stats.test.ts index 9b3c160..a4dc1e8 100644 --- a/src/ts/rtp-stats.test.ts +++ b/src/ts/rtp-stats.test.ts @@ -18,7 +18,6 @@ describe("RTP Statistics", () => { const statsResult = depayloader.getElementProperty("stats"); - await new Promise(resolve => setTimeout(resolve, 10)); await pipeline.stop(); expect(statsResult).toBeDefined(); @@ -102,7 +101,6 @@ describe("RTP Statistics", () => { const statsResult = sink.getElementProperty("stats"); - await new Promise(resolve => setTimeout(resolve, 10)); await pipeline.stop(); // fakesink has stats but different type (basesink stats, not RTP depayload stats) From da7c8e5297ab2147714430e3e2ff73127cf7d030 Mon Sep 17 00:00:00 2001 From: Serhii Mamedov Date: Thu, 25 Jun 2026 15:13:02 +0300 Subject: [PATCH 9/9] Update c++ includes for in vscode --- .vscode/c_cpp_properties.json | 30 ++++++++++++++++++++++-------- 1 file changed, 22 insertions(+), 8 deletions(-) diff --git a/.vscode/c_cpp_properties.json b/.vscode/c_cpp_properties.json index 191f032..d9b1f65 100644 --- a/.vscode/c_cpp_properties.json +++ b/.vscode/c_cpp_properties.json @@ -3,19 +3,33 @@ { "name": "linux-gcc-x64", "includePath": [ - "${workspaceFolder}/**", + "${workspaceFolder}", + "${workspaceFolder}/src/cpp", + "${workspaceFolder}/node_modules/node-addon-api", + "/usr/include/node", "/usr/include/gstreamer-1.0", + "/usr/include/orc-0.4", "/usr/include/x86_64-linux-gnu", "/usr/include/glib-2.0", - "/usr/lib/x86_64-linux-gnu/glib-2.0/include", - "${workspaceFolder}/node_modules/node-addon-api" + "/usr/lib/x86_64-linux-gnu/glib-2.0/include" ], - "compilerPath": "/usr/lib/ccache/gcc", - "cStandard": "${default}", - "cppStandard": "${default}", + "browse": { + "path": [ + "${workspaceFolder}/src/cpp", + "${workspaceFolder}/node_modules/node-addon-api", + "/usr/include/node", + "/usr/include/gstreamer-1.0", + "/usr/include/orc-0.4", + "/usr/include/x86_64-linux-gnu", + "/usr/include/glib-2.0", + "/usr/lib/x86_64-linux-gnu/glib-2.0/include" + ] + }, + "compilerPath": "/usr/bin/g++", + "cStandard": "c17", + "cppStandard": "c++20", "intelliSenseMode": "linux-gcc-x64", - "compilerArgs": [""], - "defines": ["NAPI_CPP_EXCEPTIONS", "BUILDING_NODE_EXTENSION"] + "defines": ["NAPI_VERSION=9", "NAPI_DISABLE_CPP_EXCEPTIONS", "BUILDING_NODE_EXTENSION"] } ], "version": 4