From 582bc178835ef24702f1b71b45e655f75aa122dd Mon Sep 17 00:00:00 2001 From: Jinghui Liao Date: Tue, 3 Oct 2023 20:50:38 +0800 Subject: [PATCH 1/5] add couple of regex methods to the devpack --- src/Neo.SmartContract.Framework/Regex.cs | 64 +++++++++++++++++ .../RegexTest.cs | 72 +++++++++++++++++++ .../TestClasses/Contract_Regex.cs | 37 ++++++++++ 3 files changed, 173 insertions(+) create mode 100644 src/Neo.SmartContract.Framework/Regex.cs create mode 100644 tests/Neo.SmartContract.Framework.UnitTests/RegexTest.cs create mode 100644 tests/Neo.SmartContract.Framework.UnitTests/TestClasses/Contract_Regex.cs diff --git a/src/Neo.SmartContract.Framework/Regex.cs b/src/Neo.SmartContract.Framework/Regex.cs new file mode 100644 index 000000000..88706e331 --- /dev/null +++ b/src/Neo.SmartContract.Framework/Regex.cs @@ -0,0 +1,64 @@ +using Neo.SmartContract.Framework.Native; +namespace Neo.SmartContract.Framework; + +public class Regex +{ + public static bool NumberOnly(ByteString byteString) + { + foreach (var value in byteString) + { + if (value is < 48 or > 57) + return false; + } + return true; + } + + public static bool AlphabetOnly(ByteString byteString) + { + foreach (var value in byteString) + { + if (value is < 65 or > 122) + return false; + } + return true; + } + + + /// + /// Returns the index of the first occurrence of a given value in an array. + /// + /// Array where to search. + /// Array to search. + /// Index where it is located or -1 + public static int IndexOf(ByteString byteString, ByteString byteToFind) + { + return StdLib.MemorySearch(byteString, byteToFind); + } + + /// + /// Determines whether the beginning of this string instance matches the specified string when compared using the specified culture. + /// + /// Array where to search. + /// Array to search. + /// True if start with + public static bool StartWith(ByteString byteString, ByteString byteToFind) + { + return StdLib.MemorySearch(byteString, byteToFind) == 0; + } + + /// + /// Determines whether the end of this string instance matches a specified string. + /// + /// Array where to search. + /// Array to search. + /// True if ends with + public static bool EndsWith(ByteString byteString, ByteString byteToFind) + { + return StdLib.MemorySearch(byteString, byteToFind) + byteToFind.Length == byteString.Length; + } + + public static bool Contains(ByteString byteString, ByteString byteToFind) + { + return StdLib.MemorySearch(byteString, byteToFind) != -1; + } +} diff --git a/tests/Neo.SmartContract.Framework.UnitTests/RegexTest.cs b/tests/Neo.SmartContract.Framework.UnitTests/RegexTest.cs new file mode 100644 index 000000000..ed1facd9a --- /dev/null +++ b/tests/Neo.SmartContract.Framework.UnitTests/RegexTest.cs @@ -0,0 +1,72 @@ +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Neo.Compiler.CSharp.UnitTests.Utils; +using Neo.VM.Types; + +namespace Neo.SmartContract.Framework.UnitTests +{ + [TestClass] + public class RegexTest + { + private TestEngine _engine; + + [TestInitialize] + public void Init() + { + _engine = new TestEngine(snapshot: new TestDataCache()); + _engine.AddEntryScript("./TestClasses/Contract_Regex.cs"); + } + + [TestMethod] + public void TestStartWith() + { + var result = _engine.ExecuteTestCaseStandard("testStartWith"); + Assert.AreEqual(1, result.Count); + var item = result.Pop(); + Assert.IsTrue(item.GetBoolean()); + } + + [TestMethod] + public void TestIndexOf() + { + _engine.Reset(); + var result = _engine.ExecuteTestCaseStandard("testIndexOf"); + Assert.AreEqual(1, result.Count); + var item = result.Pop(); + Assert.AreEqual(4, item.GetInteger()); + } + + [TestMethod] + public void TestEndWith() + { + var result = _engine.ExecuteTestCaseStandard("testEndWith"); + Assert.AreEqual(1, result.Count); + var item = result.Pop(); + Assert.IsTrue(item.GetBoolean()); + } + [TestMethod] + public void TestContains() + { + var result = _engine.ExecuteTestCaseStandard("testContains"); + Assert.AreEqual(1, result.Count); + var item = result.Pop(); + Assert.IsTrue(item.GetBoolean()); + } + + [TestMethod] + public void TestNumberOnly() + { + var result = _engine.ExecuteTestCaseStandard("testNumberOnly"); + Assert.AreEqual(1, result.Count); + var item = result.Pop(); + Assert.IsTrue(item.GetBoolean()); + } + [TestMethod] + public void TestAlphabetOnly() + { + var result = _engine.ExecuteTestCaseStandard("testAlphabetOnly"); + Assert.AreEqual(1, result.Count); + var item = result.Pop(); + Assert.IsTrue(item.GetBoolean()); + } + } +} diff --git a/tests/Neo.SmartContract.Framework.UnitTests/TestClasses/Contract_Regex.cs b/tests/Neo.SmartContract.Framework.UnitTests/TestClasses/Contract_Regex.cs new file mode 100644 index 000000000..d67987264 --- /dev/null +++ b/tests/Neo.SmartContract.Framework.UnitTests/TestClasses/Contract_Regex.cs @@ -0,0 +1,37 @@ +using Neo.SmartContract.Framework; + +namespace Neo.SmartContract.Framework.UnitTests.TestClasses +{ + public class Contract_Regex : SmartContract + { + public static bool TestStartWith() + { + return Regex.StartWith("Hello World", "Hello"); + } + + public static int TestIndexOf() + { + return Regex.IndexOf("Hello World", "o"); + } + + public static bool TestEndWith() + { + return Regex.EndsWith("Hello World", "World"); + } + + public static bool TestContains() + { + return Regex.Contains("Hello World", "ll"); + } + + public static bool TestNumberOnly() + { + return Regex.NumberOnly("1234567890"); + } + + public static bool TestAlphabetOnly() + { + return Regex.AlphabetOnly("HelloWorld"); + } + } +} From 77a6458a0845b758e33bdca8442ffc3f8cb6d51d Mon Sep 17 00:00:00 2001 From: Fernando Diaz Toledano Date: Wed, 4 Oct 2023 09:27:13 +0200 Subject: [PATCH 2/5] Rename methods --- src/Neo.SmartContract.Framework/Regex.cs | 15 ++++++++++++--- .../TestClasses/Contract_Regex.cs | 4 ++-- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/src/Neo.SmartContract.Framework/Regex.cs b/src/Neo.SmartContract.Framework/Regex.cs index 88706e331..209e6b771 100644 --- a/src/Neo.SmartContract.Framework/Regex.cs +++ b/src/Neo.SmartContract.Framework/Regex.cs @@ -3,7 +3,12 @@ namespace Neo.SmartContract.Framework; public class Regex { - public static bool NumberOnly(ByteString byteString) + /// + /// Denotes whether provided character is a number. + /// + /// Input to check + /// True if is number + public static bool IsNumber(ByteString byteString) { foreach (var value in byteString) { @@ -13,7 +18,12 @@ public static bool NumberOnly(ByteString byteString) return true; } - public static bool AlphabetOnly(ByteString byteString) + /// + /// Denotes whether provided character is a lowercase letter. + /// + /// Input to check + /// True if is Alpha character + public static bool IsAlphabet(ByteString byteString) { foreach (var value in byteString) { @@ -23,7 +33,6 @@ public static bool AlphabetOnly(ByteString byteString) return true; } - /// /// Returns the index of the first occurrence of a given value in an array. /// diff --git a/tests/Neo.SmartContract.Framework.UnitTests/TestClasses/Contract_Regex.cs b/tests/Neo.SmartContract.Framework.UnitTests/TestClasses/Contract_Regex.cs index d67987264..7367ec674 100644 --- a/tests/Neo.SmartContract.Framework.UnitTests/TestClasses/Contract_Regex.cs +++ b/tests/Neo.SmartContract.Framework.UnitTests/TestClasses/Contract_Regex.cs @@ -26,12 +26,12 @@ public static bool TestContains() public static bool TestNumberOnly() { - return Regex.NumberOnly("1234567890"); + return Regex.IsNumber("1234567890"); } public static bool TestAlphabetOnly() { - return Regex.AlphabetOnly("HelloWorld"); + return Regex.IsAlphabet("HelloWorld"); } } } From 9cf491e6f3e9d15db567be3c66d5e6cf62cbbd69 Mon Sep 17 00:00:00 2001 From: Fernando Diaz Toledano Date: Wed, 4 Oct 2023 09:27:46 +0200 Subject: [PATCH 3/5] Clean code --- tests/Neo.SmartContract.Framework.UnitTests/RegexTest.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/Neo.SmartContract.Framework.UnitTests/RegexTest.cs b/tests/Neo.SmartContract.Framework.UnitTests/RegexTest.cs index ed1facd9a..971931eb3 100644 --- a/tests/Neo.SmartContract.Framework.UnitTests/RegexTest.cs +++ b/tests/Neo.SmartContract.Framework.UnitTests/RegexTest.cs @@ -60,6 +60,7 @@ public void TestNumberOnly() var item = result.Pop(); Assert.IsTrue(item.GetBoolean()); } + [TestMethod] public void TestAlphabetOnly() { From 66b7d2e067b08dff188f62680074e388b39b9245 Mon Sep 17 00:00:00 2001 From: Jim8y Date: Mon, 26 Feb 2024 15:29:40 +0800 Subject: [PATCH 4/5] update regex methods --- .../{Regex.cs => ByteString.Extension.cs} | 46 +++++++++++++++---- .../Contract_Regex.cs | 45 ++++++++++++++++++ .../RegexTest.cs | 21 ++++++--- .../Services/ContractTest.cs | 1 - .../TestClasses/Contract_Regex.cs | 37 --------------- .../neocontractoracle/OracleRequestTests.cs | 2 +- 6 files changed, 99 insertions(+), 53 deletions(-) rename src/Neo.SmartContract.Framework/{Regex.cs => ByteString.Extension.cs} (58%) create mode 100644 tests/Neo.SmartContract.Framework.TestContracts/Contract_Regex.cs delete mode 100644 tests/Neo.SmartContract.Framework.UnitTests/TestClasses/Contract_Regex.cs diff --git a/src/Neo.SmartContract.Framework/Regex.cs b/src/Neo.SmartContract.Framework/ByteString.Extension.cs similarity index 58% rename from src/Neo.SmartContract.Framework/Regex.cs rename to src/Neo.SmartContract.Framework/ByteString.Extension.cs index 209e6b771..86a9fbd08 100644 --- a/src/Neo.SmartContract.Framework/Regex.cs +++ b/src/Neo.SmartContract.Framework/ByteString.Extension.cs @@ -1,14 +1,14 @@ using Neo.SmartContract.Framework.Native; namespace Neo.SmartContract.Framework; -public class Regex +public static class ByteStringExtension { /// /// Denotes whether provided character is a number. /// /// Input to check /// True if is number - public static bool IsNumber(ByteString byteString) + public static bool IsNumber(this ByteString byteString) { foreach (var value in byteString) { @@ -23,11 +23,41 @@ public static bool IsNumber(ByteString byteString) /// /// Input to check /// True if is Alpha character - public static bool IsAlphabet(ByteString byteString) + public static bool IsLowerAlphabet(this ByteString byteString) { foreach (var value in byteString) { - if (value is < 65 or > 122) + if (value is < 97 or > 122) + return false; + } + return true; + } + + /// + /// Denotes whether provided character is a lowercase letter. + /// + /// Input to check + /// True if is Alpha character + public static bool IsUpperAlphabet(this ByteString byteString) + { + foreach (var value in byteString) + { + if (value is < 65 or > 90) + return false; + } + return true; + } + + /// + /// Denotes whether provided character is a lowercase letter. + /// + /// Input to check + /// True if is Alpha character + public static bool IsAlphabet(this ByteString byteString) + { + foreach (var value in byteString) + { + if (!((value >= 65 && value <= 90) || (value >= 97 && value <= 122))) return false; } return true; @@ -39,7 +69,7 @@ public static bool IsAlphabet(ByteString byteString) /// Array where to search. /// Array to search. /// Index where it is located or -1 - public static int IndexOf(ByteString byteString, ByteString byteToFind) + public static int IndexOf(this ByteString byteString, ByteString byteToFind) { return StdLib.MemorySearch(byteString, byteToFind); } @@ -50,7 +80,7 @@ public static int IndexOf(ByteString byteString, ByteString byteToFind) /// Array where to search. /// Array to search. /// True if start with - public static bool StartWith(ByteString byteString, ByteString byteToFind) + public static bool StartWith(this ByteString byteString, ByteString byteToFind) { return StdLib.MemorySearch(byteString, byteToFind) == 0; } @@ -61,12 +91,12 @@ public static bool StartWith(ByteString byteString, ByteString byteToFind) /// Array where to search. /// Array to search. /// True if ends with - public static bool EndsWith(ByteString byteString, ByteString byteToFind) + public static bool EndsWith(this ByteString byteString, ByteString byteToFind) { return StdLib.MemorySearch(byteString, byteToFind) + byteToFind.Length == byteString.Length; } - public static bool Contains(ByteString byteString, ByteString byteToFind) + public static bool Contains(this ByteString byteString, ByteString byteToFind) { return StdLib.MemorySearch(byteString, byteToFind) != -1; } diff --git a/tests/Neo.SmartContract.Framework.TestContracts/Contract_Regex.cs b/tests/Neo.SmartContract.Framework.TestContracts/Contract_Regex.cs new file mode 100644 index 000000000..718ef879b --- /dev/null +++ b/tests/Neo.SmartContract.Framework.TestContracts/Contract_Regex.cs @@ -0,0 +1,45 @@ +namespace Neo.SmartContract.Framework.UnitTests.TestClasses +{ + public class Contract_Regex : SmartContract + { + public static bool TestStartWith() + { + return ((ByteString)"Hello World").StartWith("Hello"); + } + + public static int TestIndexOf() + { + return ((ByteString)"Hello World").IndexOf("o"); + } + + public static bool TestEndWith() + { + return ((ByteString)"Hello World").EndsWith("World"); + } + + public static bool TestContains() + { + return ((ByteString)"Hello World").Contains("ll"); + } + + public static bool TestNumberOnly() + { + return ((ByteString)"0123456789").IsNumber(); + } + + public static bool TestAlphabetOnly() + { + return ((ByteString)"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz").IsAlphabet(); + } + + public static bool TestLowerAlphabetOnly() + { + return ((ByteString)"abcdefghijklmnopqrstuvwxyz").IsAlphabet(); + } + + public static bool TestUpperAlphabetOnly() + { + return ((ByteString)"ABCDEFGHIJKLMNOPQRSTUVWXYZ").IsAlphabet(); + } + } +} diff --git a/tests/Neo.SmartContract.Framework.UnitTests/RegexTest.cs b/tests/Neo.SmartContract.Framework.UnitTests/RegexTest.cs index 971931eb3..4ff505b97 100644 --- a/tests/Neo.SmartContract.Framework.UnitTests/RegexTest.cs +++ b/tests/Neo.SmartContract.Framework.UnitTests/RegexTest.cs @@ -1,19 +1,19 @@ using Microsoft.VisualStudio.TestTools.UnitTesting; -using Neo.Compiler.CSharp.UnitTests.Utils; using Neo.VM.Types; +using Neo.SmartContract.TestEngine; namespace Neo.SmartContract.Framework.UnitTests { [TestClass] public class RegexTest { - private TestEngine _engine; + private TestEngine.TestEngine _engine; [TestInitialize] public void Init() { - _engine = new TestEngine(snapshot: new TestDataCache()); - _engine.AddEntryScript("./TestClasses/Contract_Regex.cs"); + _engine = new TestEngine.TestEngine(snapshot: new TestDataCache()); + _engine.AddEntryScript(Utils.Extensions.TestContractRoot + "Contract_Regex.cs"); } [TestMethod] @@ -66,8 +66,17 @@ public void TestAlphabetOnly() { var result = _engine.ExecuteTestCaseStandard("testAlphabetOnly"); Assert.AreEqual(1, result.Count); - var item = result.Pop(); - Assert.IsTrue(item.GetBoolean()); + Assert.IsTrue(result.Pop().GetBoolean()); + + _engine.Reset(); + result = _engine.ExecuteTestCaseStandard("testLowerAlphabetOnly"); + Assert.AreEqual(1, result.Count); + Assert.IsTrue(result.Pop().GetBoolean()); + + _engine.Reset(); + result = _engine.ExecuteTestCaseStandard("testUpperAlphabetOnly"); + Assert.AreEqual(1, result.Count); + Assert.IsTrue(result.Pop().GetBoolean()); } } } diff --git a/tests/Neo.SmartContract.Framework.UnitTests/Services/ContractTest.cs b/tests/Neo.SmartContract.Framework.UnitTests/Services/ContractTest.cs index b05518240..aa364aec8 100644 --- a/tests/Neo.SmartContract.Framework.UnitTests/Services/ContractTest.cs +++ b/tests/Neo.SmartContract.Framework.UnitTests/Services/ContractTest.cs @@ -5,7 +5,6 @@ using Neo.VM; using Neo.VM.Types; using System; -using Neo.Persistence; using Neo.SmartContract.TestEngine; using Array = Neo.VM.Types.Array; diff --git a/tests/Neo.SmartContract.Framework.UnitTests/TestClasses/Contract_Regex.cs b/tests/Neo.SmartContract.Framework.UnitTests/TestClasses/Contract_Regex.cs deleted file mode 100644 index 7367ec674..000000000 --- a/tests/Neo.SmartContract.Framework.UnitTests/TestClasses/Contract_Regex.cs +++ /dev/null @@ -1,37 +0,0 @@ -using Neo.SmartContract.Framework; - -namespace Neo.SmartContract.Framework.UnitTests.TestClasses -{ - public class Contract_Regex : SmartContract - { - public static bool TestStartWith() - { - return Regex.StartWith("Hello World", "Hello"); - } - - public static int TestIndexOf() - { - return Regex.IndexOf("Hello World", "o"); - } - - public static bool TestEndWith() - { - return Regex.EndsWith("Hello World", "World"); - } - - public static bool TestContains() - { - return Regex.Contains("Hello World", "ll"); - } - - public static bool TestNumberOnly() - { - return Regex.IsNumber("1234567890"); - } - - public static bool TestAlphabetOnly() - { - return Regex.IsAlphabet("HelloWorld"); - } - } -} diff --git a/tests/Neo.SmartContract.Template.UnitTests/templates/neocontractoracle/OracleRequestTests.cs b/tests/Neo.SmartContract.Template.UnitTests/templates/neocontractoracle/OracleRequestTests.cs index 38b3fd537..c9a83b933 100644 --- a/tests/Neo.SmartContract.Template.UnitTests/templates/neocontractoracle/OracleRequestTests.cs +++ b/tests/Neo.SmartContract.Template.UnitTests/templates/neocontractoracle/OracleRequestTests.cs @@ -9,7 +9,7 @@ namespace Neo.SmartContract.Template.UnitTests.templates.neocontractowner { /// - /// You need to build the solution to resolve Ownable class. + /// You need to build the solution to resolve OracleRequest class. /// [TestClass] public class OracleRequestTests : TestBase From 1981bdd95bd196d7bfae2a9228cf259ca7305d1b Mon Sep 17 00:00:00 2001 From: Jim8y Date: Mon, 26 Feb 2024 17:24:15 +0800 Subject: [PATCH 5/5] add comments --- src/Neo.SmartContract.Framework/ByteString.Extension.cs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/Neo.SmartContract.Framework/ByteString.Extension.cs b/src/Neo.SmartContract.Framework/ByteString.Extension.cs index 86a9fbd08..eeae195d4 100644 --- a/src/Neo.SmartContract.Framework/ByteString.Extension.cs +++ b/src/Neo.SmartContract.Framework/ByteString.Extension.cs @@ -96,6 +96,12 @@ public static bool EndsWith(this ByteString byteString, ByteString byteToFind) return StdLib.MemorySearch(byteString, byteToFind) + byteToFind.Length == byteString.Length; } + /// + /// Checks if the contains the given . + /// + /// to search. + /// to be searched. + /// public static bool Contains(this ByteString byteString, ByteString byteToFind) { return StdLib.MemorySearch(byteString, byteToFind) != -1;