diff --git a/binding/dotnet/PorcupineTest/MainTest.cs b/binding/dotnet/PorcupineTest/MainTest.cs index 195422b8d..4abdd3e75 100644 --- a/binding/dotnet/PorcupineTest/MainTest.cs +++ b/binding/dotnet/PorcupineTest/MainTest.cs @@ -334,6 +334,35 @@ public void TestMessageStack() } } + [TestMethod] + public void TestProcessMessageStack() + { + List keywords = new List() { BuiltInKeyword.PORCUPINE }; + Porcupine p = Porcupine.FromBuiltInKeywords( + _accessKey, + keywords, + GetModelPath("en")); + short[] testPcm = new short[p.FrameLength]; + + var obj = typeof(Porcupine).GetField("_libraryPointer", BindingFlags.NonPublic | BindingFlags.Instance); + IntPtr address = (IntPtr)obj.GetValue(p); + obj.SetValue(p, IntPtr.Zero); + + try + { + int res = p.Process(testPcm); + Assert.IsTrue(res == 100); + } + catch (PorcupineException e) + { + Assert.IsTrue(0 < e.MessageStack.Length); + Assert.IsTrue(e.MessageStack.Length < 8); + } + + obj.SetValue(p, address); + p.Dispose(); + } + private List GetPcmFromFile(string audioFilePath, int expectedSampleRate) { List data = new List(); diff --git a/binding/go/porcupine_test.go b/binding/go/porcupine_test.go index 82f0d02b7..bf05f1c9c 100644 --- a/binding/go/porcupine_test.go +++ b/binding/go/porcupine_test.go @@ -307,3 +307,33 @@ func TestMessageStack(t *testing.T) { t.Fatalf("length of 1st init '%d' does not match 2nd init '%d'", len(err.Error()), len(err2.Error())) } } + +func TestProcessMessageStack(t *testing.T) { + language := "en" + keywords := []string{"porcupine"} + porcupine = Porcupine{ + AccessKey: testAccessKey, + ModelPath: getTestModelPath(language), + KeywordPaths: getTestKeywordPaths(language, keywords)} + + err := porcupine.Init() + if err != nil { + t.Fatalf("%v", err) + } + + address := porcupine.handle + porcupine.handle = nil + + testPcm := make([]int16, FrameLength) + + _, err = porcupine.Process(testPcm) + porcupine.handle = address + if err == nil { + t.Fatalf("Expected porcupine process to fail") + } + + delErr := porcupine.Delete() + if delErr != nil { + t.Fatalf("%v", delErr) + } +} diff --git a/binding/ios/PorcupineAppTest/PorcupineAppTestUITests/PorcupineAppTestUITests.swift b/binding/ios/PorcupineAppTest/PorcupineAppTestUITests/PorcupineAppTestUITests.swift index 9a9a9e695..2cdea811b 100644 --- a/binding/ios/PorcupineAppTest/PorcupineAppTestUITests/PorcupineAppTestUITests.swift +++ b/binding/ios/PorcupineAppTest/PorcupineAppTestUITests/PorcupineAppTestUITests.swift @@ -263,4 +263,19 @@ class PorcupineAppTestUITests: BaseTest { XCTAssert("\(error.localizedDescription)".count == first_error.count) } } + + func testProcessMessageStack() throws { + let p = try Porcupine.init(accessKey: accessKey, keyword: Porcupine.BuiltInKeyword.porcupine) + p.delete() + + var testPcm: [Int16] = [] + testPcm.reserveCapacity(Int(Porcupine.frameLength)) + + do { + let res = try p.process(pcm: testPcm) + XCTAssert(res == 100) + } catch { + XCTAssert("\(error.localizedDescription)".count > 0) + } + } } diff --git a/binding/python/test_porcupine.py b/binding/python/test_porcupine.py index dcfdea559..1f53b6f39 100644 --- a/binding/python/test_porcupine.py +++ b/binding/python/test_porcupine.py @@ -104,6 +104,29 @@ def test_message_stack(self): self.assertEqual(len(error), len(e.message_stack)) self.assertListEqual(list(error), list(e.message_stack)) + def test_process_message_stack(self): + relative_path = '../..' + + p = Porcupine( + access_key=sys.argv[1], + library_path=pv_library_path(relative_path), + model_path=get_model_path_by_language(relative_path, 'en'), + keyword_paths=get_keyword_paths_by_language(relative_path, 'en', ['porcupine']), + sensitivities=[0.5]) + test_pcm = [0] * p.frame_length + + address = p._handle + p._handle = None + + try: + res = p.process(test_pcm) + self.assertEqual(res, 100) + except PorcupineError as e: + self.assertGreater(len(e.message_stack), 0) + self.assertLess(len(e.message_stack), 8) + + p._handle = address + if __name__ == '__main__': if len(sys.argv) != 2: diff --git a/binding/rust/src/porcupine.rs b/binding/rust/src/porcupine.rs index 05e52232a..aee47cc25 100644 --- a/binding/rust/src/porcupine.rs +++ b/binding/rust/src/porcupine.rs @@ -593,3 +593,44 @@ impl Drop for PorcupineInner { } } } + +#[cfg(test)] +mod tests { + use std::env; + use std::path::PathBuf; + + use crate::util::{pv_keyword_paths, pv_library_path, pv_model_path}; + use crate::porcupine::{BuiltinKeywords, PorcupineInner}; + + #[test] + fn test_process_error_stack() { + let access_key = env::var("PV_ACCESS_KEY") + .expect("Pass the AccessKey in using the PV_ACCESS_KEY env variable"); + + let default_keyword_paths = pv_keyword_paths(); + let keyword_path = default_keyword_paths.get(BuiltinKeywords::Porcupine.to_str()) + .expect("Unable to find keyword file for specified keyword"); + + let mut inner = PorcupineInner::init( + &access_key.as_str(), + pv_library_path(), + pv_model_path(), + &[PathBuf::from(keyword_path)], + &[0.5], + ).expect("Unable to create Porcupine"); + + let test_pcm = vec![0; inner.frame_length as usize]; + let address = inner.cporcupine; + inner.cporcupine = std::ptr::null_mut(); + + let res = inner.process(&test_pcm); + + inner.cporcupine = address; + if let Err(err) = res { + assert!(err.message_stack.len() > 0); + assert!(err.message_stack.len() < 8); + } else { + assert!(res.unwrap() == 100); + } + } +} diff --git a/binding/unity/Assets/Porcupine/PorcupineException.cs b/binding/unity/Assets/Porcupine/PorcupineException.cs index d490634e9..41ce9ddb6 100644 --- a/binding/unity/Assets/Porcupine/PorcupineException.cs +++ b/binding/unity/Assets/Porcupine/PorcupineException.cs @@ -26,7 +26,7 @@ public PorcupineException(string message, string[] messageStack) : base(ModifyMe this._messageStack = messageStack; } - public string[] messageStack + public string[] MessageStack { get => _messageStack; } diff --git a/binding/unity/Assets/Porcupine/Tests/Integration.cs b/binding/unity/Assets/Porcupine/Tests/Integration.cs index f91754ba5..a8b5e5c27 100644 --- a/binding/unity/Assets/Porcupine/Tests/Integration.cs +++ b/binding/unity/Assets/Porcupine/Tests/Integration.cs @@ -240,7 +240,7 @@ public void TestMessageStack() } catch (PorcupineException e) { - messageList = e.messageStack; + messageList = e.MessageStack; } Assert.IsTrue(0 < messageList.Length); @@ -258,11 +258,41 @@ public void TestMessageStack() { for (int i = 0; i < messageList.Length; i++) { - Assert.AreEqual(messageList[i], e.messageStack[i]); + Assert.AreEqual(messageList[i], e.MessageStack[i]); } } } + [Test] + public void TestProcessMessageStack() + { + List keywords = new List() { Porcupine.BuiltInKeyword.PORCUPINE }; + Porcupine p = Porcupine.FromBuiltInKeywords( + ACCESS_KEY, + keywords, + GetModelPath("en")); + + short[] testPcm = new short[p.FrameLength]; + + var obj = typeof(Porcupine).GetField("_libraryPointer", BindingFlags.NonPublic | BindingFlags.Instance); + IntPtr address = (IntPtr)obj.GetValue(p); + obj.SetValue(p, IntPtr.Zero); + + try + { + int res = p.Process(testPcm); + Assert.IsTrue(res == 100); + } + catch (PorcupineException e) + { + Assert.IsTrue(0 < e.MessageStack.Length); + Assert.IsTrue(e.MessageStack.Length < 8); + } + + obj.SetValue(p, address); + p.Dispose(); + } + [Test] public void SingleKeyword([ValueSource("SingleKeywordTestData")] SingleKeywordTest testCase) { diff --git a/binding/unity/porcupine-3.0.0.unitypackage b/binding/unity/porcupine-3.0.0.unitypackage index 743ae269d..f00db8c32 100644 Binary files a/binding/unity/porcupine-3.0.0.unitypackage and b/binding/unity/porcupine-3.0.0.unitypackage differ