From 8567f280cb53b256049050cfe2981a65c6892eff Mon Sep 17 00:00:00 2001 From: Sebastian Date: Sun, 1 Oct 2023 17:34:51 +0200 Subject: [PATCH] Remove protocol Simplify for PR. Test field offset. Test Run tests again. Test t File was not saved. simple run Check tests Revert struct. Fix tests. Check some offset thing. Array tests More test fixes. Fix tests Fix check. Fix build. better result types. Set environment variable. Do not run arm tests. Do not fail fast. Test build. Test linux. Another test Print out files. Fix library name. Cp Fix path Fix yaml Try to run tests Fix path Another test Fix pack? Upload nuget packages. Checkout everything. Build props. Remove patch. Test Fix sync. Small fixes. Fix To method. Fixes Several fixed and simplifications. Setup to test more providers and authentication. Extension project. Fix project name. Add support for MongoDB. Simplified code. Batching. Fix deadlock and implement listener. Styling. Deadlock test Temp. Rename file. Service extensions. Test Some improvements. Just some progress. Cache documents. Server project. --- .cargo/config.github | 11 ++ .github/workflows/build-binaries.yml | 137 ++++++++++++++++ .github/workflows/build.yml | 82 ++++++++++ .gitignore | 8 + Directory.Build.props | 18 +++ Tests/YDotNet.Tests.Unit/Arrays/GetTests.cs | 7 +- .../YDotNet.Tests.Unit/Arrays/IterateTests.cs | 3 - .../YDotNet.Tests.Unit/Arrays/ObserveTests.cs | 2 - .../Document/UpdatesV1Tests.cs | 4 +- Tests/YDotNet.Tests.Unit/Maps/GetTests.cs | 51 ++---- Tests/YDotNet.Tests.Unit/Maps/InsertTests.cs | 7 +- Tests/YDotNet.Tests.Unit/Maps/ObserveTests.cs | 9 -- Tests/YDotNet.Tests.Unit/Texts/ChunksTests.cs | 3 - .../Texts/InsertEmbedTests.cs | 12 -- .../YDotNet.Tests.Unit/Texts/ObserveTests.cs | 1 - .../UndoManagers/RedoTests.cs | 3 +- .../UndoManagers/UndoTests.cs | 2 +- .../XmlElements/FirstChildTests.cs | 2 - .../XmlElements/GetTests.cs | 2 - .../XmlElements/NextSiblingTests.cs | 2 - .../XmlElements/ObserveTests.cs | 10 -- .../XmlElements/PreviousSiblingTests.cs | 2 - .../XmlElements/TreeWalkerTests.cs | 8 - .../XmlTexts/NextSiblingTests.cs | 2 - .../XmlTexts/ObserveTests.cs | 4 - .../XmlTexts/PreviousSiblingTests.cs | 2 - YDotNet.sln | 46 +++++- YDotNet/Document/Cells/Input.cs | 2 +- YDotNet/Document/Cells/Output.cs | 149 +++++++++++++++--- YDotNet/Document/Cells/OutputInputType.cs | 92 +++++++++++ YDotNet/Document/Options/DocOptions.cs | 4 +- YDotNet/Document/Transactions/Transaction.cs | 2 +- YDotNet/Document/Types/Maps/Map.cs | 4 +- YDotNet/Native/Cells/Inputs/InputNative.cs | 2 +- YDotNet/Native/ChannelSettings.cs | 7 +- .../Events/AfterTransactionEventNative.cs | 5 +- .../Document/State/StateVectorNative.cs | 5 +- YDotNet/Native/Types/Maps/MapChannel.cs | 2 +- YDotNet/stylecop.json | 14 ++ .../YDotNet.Native.Linux.csproj | 18 +++ .../YDotNet.Native.MacOS.csproj | 13 ++ .../YDotNet.Native.Win32.csproj | 13 ++ native/YDotNet.Native/YDotNet.Native.csproj | 15 ++ 43 files changed, 639 insertions(+), 148 deletions(-) create mode 100644 .cargo/config.github create mode 100644 .github/workflows/build-binaries.yml create mode 100644 .github/workflows/build.yml create mode 100644 Directory.Build.props create mode 100644 YDotNet/Document/Cells/OutputInputType.cs create mode 100644 YDotNet/stylecop.json create mode 100644 native/YDotNet.Native.Linux/YDotNet.Native.Linux.csproj create mode 100644 native/YDotNet.Native.MacOS/YDotNet.Native.MacOS.csproj create mode 100644 native/YDotNet.Native.Win32/YDotNet.Native.Win32.csproj create mode 100644 native/YDotNet.Native/YDotNet.Native.csproj diff --git a/.cargo/config.github b/.cargo/config.github new file mode 100644 index 00000000..91e208bc --- /dev/null +++ b/.cargo/config.github @@ -0,0 +1,11 @@ +[target.aarch64-unknown-linux-gnu] +linker = "aarch64-linux-gnu-gcc" + +[target.aarch64-unknown-linux-musl] +linker = "aarch64-linux-gnu-gcc" + +[target.armv7-unknown-linux-gnueabihf] +linker = "arm-linux-gnueabihf-gcc" + +[target.armv7-unknown-linux-musleabihf] +linker = "arm-linux-musleabihf-gcc" diff --git a/.github/workflows/build-binaries.yml b/.github/workflows/build-binaries.yml new file mode 100644 index 00000000..95260d00 --- /dev/null +++ b/.github/workflows/build-binaries.yml @@ -0,0 +1,137 @@ +name: Build Binaries + +on: + push: + tags: + - 'binaries[0-9]' +env: + YRS_REPO: https://github.com/SebastianStehle/y-crdt + YRS_BRANCH: main + CARGO_TERM_COLOR: always + +jobs: + # Based on https://www.rohanjain.in/cargo-cross/ + build-native-binaries: + runs-on: ${{matrix.os}} + strategy: + matrix: + include: + # Windows + - build: win-x64 + os: windows-latest + rust: stable + target: x86_64-pc-windows-msvc + linker: mingw-w64 + cross: false + + # Linux + - build: linux-x64 + os: ubuntu-latest + rust: stable + target: x86_64-unknown-linux-gnu + cross: false + + - build: linux-x64-musl + os: ubuntu-latest + rust: stable + target: x86_64-unknown-linux-musl + cross: false + + - build: linux-armv7 + os: ubuntu-latest + rust: stable + target: armv7-unknown-linux-gnueabihf + linker: gcc-arm-linux-gnueabihf + cross: true + + - build: linux-armv7-musl + os: ubuntu-latest + rust: stable + target: armv7-unknown-linux-musleabihf + linker: gcc-arm-linux-gnueabihf + cross: true + + - build: linux-arm64 + os: ubuntu-latest + rust: stable + target: aarch64-unknown-linux-gnu + linker: gcc-aarch64-linux-gnu + cross: true + + - build: linux-arm64-musl + os: ubuntu-latest + rust: stable + target: aarch64-unknown-linux-musl + linker: gcc-aarch64-linux-gnu + cross: true + + # MacOS + - build: macos + os: macos-latest + rust: stable + target: x86_64-apple-darwin + cross: false + + steps: + - name: Checkout repository + uses: actions/checkout@v3 + + - name: Cache + uses: actions/cache@v3 + with: + path: | + ~/.cargo/registry + ~/.cargo/git + ~/.rustup + target + key: ${{ runner.os }}-${{ matrix.rust }} + + - name: Install cross + if: matrix.cross + uses: taiki-e/install-action@v2 + with: + tool: cross + + - name: Add musl tools + run: sudo apt install -y musl musl-dev musl-tools + if: endsWith(matrix.build, '-musl') + + - name: Install Linker + if: matrix.cross + run: | + sudo apt update + sudo apt install ${{ matrix.linker }} + cat .cargo/config.github >> .cargo/config + + - name: Install Rust + run: | + rustup install ${{ matrix.rust }} + rustup target add ${{ matrix.target }} + rustup show + + - name: Clone Yrs repo + run: | + git clone ${YRS_REPO} --branch ${YRS_BRANCH} --single-branch yrs + shell: bash + + - name: Build (cargo) + if: "!matrix.cross" + run: | + cd yrs + RUSTFLAGS="-C target-feature=-crt-static" cargo build --release --target ${{ matrix.target }} + shell: bash + + - name: Build (cross) + if: matrix.cross + run: | + cd yrs + RUSTFLAGS="-C target-feature=-crt-static" cross build --release --target ${{ matrix.target }} + + - name: Upload artifacts + uses: actions/upload-artifact@v3 + with: + name: ${{ matrix.build }} + path: | + yrs/target/${{ matrix.target }}/release/*yrs.dll + yrs/target/${{ matrix.target }}/release/*yrs.so + yrs/target/${{ matrix.target }}/release/*yrs.dylib \ No newline at end of file diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 00000000..30233260 --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,82 @@ +name: CI + +on: + push: + branches: + - '*' + +jobs: + test: + runs-on: ${{matrix.os}} + strategy: + fail-fast: false + + matrix: + include: + # Windows + - build: win-x64 + os: windows-latest + + # Linux + - build: linux-x64 + os: ubuntu-latest + + - build: linux-x64-musl + os: ubuntu-latest + + # macOS + - build: macos + os: macos-latest + + steps: + - name: Checkout repository + uses: actions/checkout@v3 + + - name: Download artifacts + uses: dawidd6/action-download-artifact@v2 + with: + path: ./output + workflow: build-binaries.yml + workflow_conclusion: success + + - name: Build Test + run: | + cd T + dotnet build + + - name: Copy to Test Folder + run: | + cp output/${{matrix.build}}/*.* T/bin/Debug/net7.0 + ls output/${{matrix.build}} + ls T/bin/Debug/net7.0 + + - name: Test + run: | + cd T && dotnet run + env: + RUST_BACKTRACE: 1 + + pack-nuget: + runs-on: ubuntu-latest + needs: test + + steps: + - name: Checkout repository + uses: actions/checkout@v3 + + - name: Download artifacts + uses: dawidd6/action-download-artifact@v2 + with: + path: ./output + workflow: build-binaries.yml + workflow_conclusion: success + + - name: Nuget pack + run: | + dotnet pack -c Release + + - name: Upload artifacts + uses: actions/upload-artifact@v3 + with: + path: | + **/*.nupkg diff --git a/.gitignore b/.gitignore index 77a71251..cc56a6f4 100644 --- a/.gitignore +++ b/.gitignore @@ -29,6 +29,7 @@ bld/ [Bb]in/ [Oo]bj/ [Oo]ut/ +[Oo]utput/ msbuild.log msbuild.err msbuild.wrn @@ -39,3 +40,10 @@ msbuild.wrn # Project-specific files *.dll *.dylib + +# Node +node_modules + +apSettings.Development.json + +launchSettings.json \ No newline at end of file diff --git a/Directory.Build.props b/Directory.Build.props new file mode 100644 index 00000000..b944aacc --- /dev/null +++ b/Directory.Build.props @@ -0,0 +1,18 @@ + + + lsvviana, sebastianstehle + MIT + YDotNet provides cross=platform .Net bindings for the Yrs Rust port of Yjs. + true + true + MIT + https://github.com/LSViana/YDotNet + true + snupkg + 0.1.0 + + + + true + + diff --git a/Tests/YDotNet.Tests.Unit/Arrays/GetTests.cs b/Tests/YDotNet.Tests.Unit/Arrays/GetTests.cs index 99506ae7..51818fef 100644 --- a/Tests/YDotNet.Tests.Unit/Arrays/GetTests.cs +++ b/Tests/YDotNet.Tests.Unit/Arrays/GetTests.cs @@ -36,8 +36,7 @@ public void GetAtBeginning() // Assert Assert.That(output, Is.Not.Null); - Assert.That(output.Boolean, Is.True); - Assert.That(output.Long, Is.Null); + Assert.That(output.Type, Is.EqualTo(OutputInputType.Bool)); } [Test] @@ -54,7 +53,6 @@ public void GetAtMiddle() // Assert Assert.That(output, Is.Not.Null); Assert.That(output.Undefined, Is.True); - Assert.That(output.Long, Is.Null); } [Test] @@ -71,7 +69,6 @@ public void GetAtEnding() // Assert Assert.That(output, Is.Not.Null); Assert.That(output.String, Is.EqualTo("Lucas")); - Assert.That(output.Long, Is.Null); } [Test] @@ -89,11 +86,9 @@ public void GetMultipleTimesAtSameIndex() // Assert Assert.That(output1, Is.Not.Null); Assert.That(output1.Boolean, Is.True); - Assert.That(output1.Long, Is.Null); Assert.That(output2, Is.Not.Null); Assert.That(output2.Boolean, Is.True); - Assert.That(output2.Long, Is.Null); } [Test] diff --git a/Tests/YDotNet.Tests.Unit/Arrays/IterateTests.cs b/Tests/YDotNet.Tests.Unit/Arrays/IterateTests.cs index 34ef428f..2dec154b 100644 --- a/Tests/YDotNet.Tests.Unit/Arrays/IterateTests.cs +++ b/Tests/YDotNet.Tests.Unit/Arrays/IterateTests.cs @@ -74,10 +74,7 @@ public void IteratesOnMultiItem() // Assert Assert.That(values.Length, Is.EqualTo(expected: 3)); Assert.That(values[0].Long, Is.EqualTo(expected: 2469L)); - Assert.That(values[0].Double, Is.Null); Assert.That(values[1].Boolean, Is.False); - Assert.That(values[1].Double, Is.Null); Assert.That(values[2].Undefined, Is.True); - Assert.That(values[2].Double, Is.Null); } } diff --git a/Tests/YDotNet.Tests.Unit/Arrays/ObserveTests.cs b/Tests/YDotNet.Tests.Unit/Arrays/ObserveTests.cs index ae495a5e..c49221e4 100644 --- a/Tests/YDotNet.Tests.Unit/Arrays/ObserveTests.cs +++ b/Tests/YDotNet.Tests.Unit/Arrays/ObserveTests.cs @@ -48,7 +48,6 @@ public void ObserveHasDeltasWhenAdded() Assert.That(eventChanges.First().Tag, Is.EqualTo(EventChangeTag.Add)); Assert.That(eventChanges.First().Length, Is.EqualTo(expected: 1)); Assert.That(eventChanges.First().Values.First().Long, Is.EqualTo(expected: 2469L)); - Assert.That(eventChanges.First().Values.First().Double, Is.Null); } [Test] @@ -118,7 +117,6 @@ public void ObserveHasDeltasWhenMoved() Assert.That(eventChanges.ElementAt(index: 0).Tag, Is.EqualTo(EventChangeTag.Add)); Assert.That(eventChanges.ElementAt(index: 0).Length, Is.EqualTo(expected: 1)); Assert.That(eventChanges.ElementAt(index: 0).Values.First().Undefined, Is.True); - Assert.That(eventChanges.ElementAt(index: 0).Values.First().Double, Is.Null); Assert.That(eventChanges.ElementAt(index: 1).Tag, Is.EqualTo(EventChangeTag.Retain)); Assert.That(eventChanges.ElementAt(index: 1).Length, Is.EqualTo(expected: 2)); diff --git a/Tests/YDotNet.Tests.Unit/Document/UpdatesV1Tests.cs b/Tests/YDotNet.Tests.Unit/Document/UpdatesV1Tests.cs index 3b3bd0a9..0bc2e8f1 100644 --- a/Tests/YDotNet.Tests.Unit/Document/UpdatesV1Tests.cs +++ b/Tests/YDotNet.Tests.Unit/Document/UpdatesV1Tests.cs @@ -30,7 +30,7 @@ public void TriggersWhenTransactionIsCommittedUntilUnobserve() // Assert Assert.That(called, Is.EqualTo(expected: 1)); Assert.That(data, Is.Not.Null); - Assert.That(data, Has.Length.InRange(from: 25, to: 30)); + Assert.That(data, Has.Length.InRange(from: 20, to: 30)); // Act data = null; @@ -41,7 +41,7 @@ public void TriggersWhenTransactionIsCommittedUntilUnobserve() // Assert Assert.That(called, Is.EqualTo(expected: 2)); Assert.That(data, Is.Not.Null); - Assert.That(data, Has.Length.InRange(from: 25, to: 31)); + Assert.That(data, Has.Length.InRange(from: 20, to: 31)); // Act data = null; diff --git a/Tests/YDotNet.Tests.Unit/Maps/GetTests.cs b/Tests/YDotNet.Tests.Unit/Maps/GetTests.cs index 848d728f..599662a6 100644 --- a/Tests/YDotNet.Tests.Unit/Maps/GetTests.cs +++ b/Tests/YDotNet.Tests.Unit/Maps/GetTests.cs @@ -1,3 +1,4 @@ +using Newtonsoft.Json.Linq; using NUnit.Framework; using YDotNet.Document; using YDotNet.Document.Cells; @@ -91,11 +92,11 @@ public void GetBytes() // Act var value1 = map.Get(transaction, "value1").Bytes; - var value2 = map.Get(transaction, "value2").Bytes; + var value2 = map.Get(transaction, "value2"); // Assert Assert.That(value1, Is.EqualTo(new byte[] { 2, 4, 6, 9 })); - Assert.That(value2, Is.Null); + Assert.That(value2.Type, Is.EqualTo(OutputInputType.Bool)); } [Test] @@ -114,14 +115,14 @@ public void GetCollection() // Act var value1 = map.Get(transaction, "value1").Collection; - var value2 = map.Get(transaction, "value2").Collection; + var value2 = map.Get(transaction, "value2"); // Assert //Assert.That(value1, Is.EqualTo(new byte[] { 2, 4, 6, 9 })); Assert.That(value1.Length, Is.EqualTo(expected: 2)); Assert.That(value1[0].Long, Is.EqualTo(expected: 2469)); Assert.That(value1[1].Long, Is.EqualTo(expected: -420L)); - Assert.That(value2, Is.Null); + Assert.That(value2.Type, Is.EqualTo(OutputInputType.Bool)); } [Test] @@ -140,13 +141,13 @@ public void GetObject() // Act var value1 = map.Get(transaction, "value1").Object; - var value2 = map.Get(transaction, "value2").Object; + var value2 = map.Get(transaction, "value2"); // Assert Assert.That(value1.Keys.Count, Is.EqualTo(expected: 2)); Assert.That(value1["star-⭐"].Long, Is.EqualTo(expected: 2469)); Assert.That(value1["moon-🌕"].Long, Is.EqualTo(expected: -420L)); - Assert.That(value2, Is.Null); + Assert.That(value2.Type, Is.EqualTo(OutputInputType.Bool)); } [Test] @@ -202,12 +203,12 @@ public void GetText() // Act var value1 = map.Get(transaction, "value1").Text; - var value2 = map.Get(transaction, "value2").Text; + var value2 = map.Get(transaction, "value2"); // Assert Assert.That(value1, Is.Not.Null); Assert.That(value1.String(transaction), Is.EqualTo("Lucas")); - Assert.That(value2, Is.Null); + Assert.That(value2.Type, Is.EqualTo(OutputInputType.Bool)); } [Test] @@ -226,12 +227,12 @@ public void GetArray() // Act var value1 = map.Get(transaction, "value1").Array; - var value2 = map.Get(transaction, "value2").Array; + var value2 = map.Get(transaction, "value2"); // Assert Assert.That(value1, Is.Not.Null); Assert.That(value1.Length, Is.EqualTo(expected: 2)); - Assert.That(value2, Is.Null); + Assert.That(value2.Type, Is.EqualTo(OutputInputType.Null)); } [Test] @@ -250,14 +251,14 @@ public void GetMap() // Act var value1 = map.Get(transaction, "value1").Map; - var value2 = map.Get(transaction, "value2").Map; + var value2 = map.Get(transaction, "value2"); // Assert Assert.That(value1, Is.Not.Null); Assert.That(value1.Length(transaction), Is.EqualTo(expected: 2)); Assert.That(value1.Get(transaction, "value1-1").Long, Is.EqualTo(expected: 2469L)); Assert.That(value1.Get(transaction, "value1-2").Long, Is.EqualTo(expected: -420L)); - Assert.That(value2, Is.Null); + Assert.That(value2.Type, Is.EqualTo(OutputInputType.Bool)); } [Test] @@ -271,12 +272,12 @@ public void GetXmlElement() // Act var value1 = map.Get(transaction, "value1").XmlElement; - var value2 = map.Get(transaction, "value2").XmlElement; + var value2 = map.Get(transaction, "value2"); // Assert Assert.That(value1, Is.Not.Null); Assert.That(value1.Tag, Is.EqualTo("person")); - Assert.That(value2, Is.Null); + Assert.That(value2.Type, Is.EqualTo(OutputInputType.Null)); } [Test] @@ -290,12 +291,12 @@ public void GetXmlText() // Act var value1 = map.Get(transaction, "value1").XmlText; - var value2 = map.Get(transaction, "value2").XmlText; + var value2 = map.Get(transaction, "value2"); // Assert Assert.That(value1, Is.Not.Null); Assert.That(value1.Length(transaction), Is.EqualTo(expected: 5)); - Assert.That(value2, Is.Null); + Assert.That(value2.Type, Is.EqualTo(OutputInputType.Null)); } [Test] @@ -312,24 +313,6 @@ public void GetDoc() Assert.That(subDoc.Id, Is.EqualTo(subDocFromMap.Id)); } - [Test] - public void GetWrongTypeOnExistingKeyReturnsNull() - { - // Arrange - var (map, transaction) = ArrangeDoc( - ("value1", Input.Long(value: 2469L)), - ("value2", Input.Double(value: 4.20)) - ); - - // Act - var value1 = map.Get(transaction, "value1").Double; - var value2 = map.Get(transaction, "value2").Long; - - // Assert - Assert.That(value1, Is.Null); - Assert.That(value2, Is.Null); - } - [Test] public void GetNewKeyReturnsNull() { diff --git a/Tests/YDotNet.Tests.Unit/Maps/InsertTests.cs b/Tests/YDotNet.Tests.Unit/Maps/InsertTests.cs index 559d0b8e..dc352029 100644 --- a/Tests/YDotNet.Tests.Unit/Maps/InsertTests.cs +++ b/Tests/YDotNet.Tests.Unit/Maps/InsertTests.cs @@ -317,15 +317,14 @@ public void InsertDifferentTypeOnExistingKey() map.Insert(transaction, "value", Input.Long(value: 2469L)); map.Insert(transaction, "value", Input.String("Lucas")); - var longValue = map.Get(transaction, "value").Long; - var stringValue = map.Get(transaction, "value").String; + var value = map.Get(transaction, "value"); var length = map.Length(transaction); transaction.Commit(); // Assert - Assert.That(longValue, Is.EqualTo(expected: null)); - Assert.That(stringValue, Is.EqualTo("Lucas")); + Assert.That(value.Type, Is.EqualTo(OutputInputType.String)); + Assert.That(value.String, Is.EqualTo("Lucas")); Assert.That(length, Is.EqualTo(expected: 1)); } diff --git a/Tests/YDotNet.Tests.Unit/Maps/ObserveTests.cs b/Tests/YDotNet.Tests.Unit/Maps/ObserveTests.cs index b4075643..bc8657f0 100644 --- a/Tests/YDotNet.Tests.Unit/Maps/ObserveTests.cs +++ b/Tests/YDotNet.Tests.Unit/Maps/ObserveTests.cs @@ -61,7 +61,6 @@ public void ObserveHasKeysWhenAdded() Assert.That(firstKey.OldValue, Is.Null); Assert.That(firstKey.NewValue, Is.Not.Null); Assert.That(firstKey.NewValue.Long, Is.EqualTo(expected: 2469L)); - Assert.That(firstKey.NewValue.Double, Is.Null); } [Test] @@ -102,7 +101,6 @@ public void ObserveHasKeysWhenRemovedByKey() Assert.That(firstKey.OldValue, Is.Not.Null); Assert.That(firstKey.NewValue, Is.Null); Assert.That(firstKey.OldValue.Long, Is.EqualTo(expected: 2469L)); - Assert.That(firstKey.OldValue.Double, Is.Null); } [Test] @@ -142,7 +140,6 @@ public void ObserveHasKeysWhenRemovedAll() Assert.That(firstKey.OldValue, Is.Not.Null); Assert.That(firstKey.NewValue, Is.Null); Assert.That(firstKey.OldValue.Long, Is.EqualTo(expected: 2469L)); - Assert.That(firstKey.OldValue.Double, Is.Null); } [Test] @@ -182,9 +179,7 @@ public void ObserveHasKeysWhenUpdated() Assert.That(firstKey.OldValue, Is.Not.Null); Assert.That(firstKey.NewValue, Is.Not.Null); Assert.That(firstKey.OldValue.Long, Is.EqualTo(expected: 2469L)); - Assert.That(firstKey.OldValue.Double, Is.Null); Assert.That(firstKey.NewValue.Long, Is.EqualTo(expected: -420L)); - Assert.That(firstKey.NewValue.Double, Is.Null); } [Test] @@ -231,20 +226,16 @@ public void ObserveHasKeysWhenAddedAndRemovedAndUpdated() Assert.That(update.OldValue, Is.Not.Null); Assert.That(update.NewValue, Is.Not.Null); Assert.That(update.OldValue.Long, Is.EqualTo(expected: 2469L)); - Assert.That(update.OldValue.Double, Is.Null); Assert.That(update.NewValue.Long, Is.EqualTo(expected: -420L)); - Assert.That(update.NewValue.Double, Is.Null); var remove = keyChanges.First(x => x.Tag == EventKeyChangeTag.Remove); Assert.That(remove.OldValue, Is.Not.Null); Assert.That(remove.NewValue, Is.Null); Assert.That(remove.OldValue.Long, Is.EqualTo(expected: -420L)); - Assert.That(remove.OldValue.Double, Is.Null); var add = keyChanges.First(x => x.Tag == EventKeyChangeTag.Add); Assert.That(add.OldValue, Is.Null); Assert.That(add.NewValue, Is.Not.Null); Assert.That(add.NewValue.Long, Is.EqualTo(expected: -1337L)); - Assert.That(add.NewValue.Double, Is.Null); } } diff --git a/Tests/YDotNet.Tests.Unit/Texts/ChunksTests.cs b/Tests/YDotNet.Tests.Unit/Texts/ChunksTests.cs index 9e9ebb2d..5db229e3 100644 --- a/Tests/YDotNet.Tests.Unit/Texts/ChunksTests.cs +++ b/Tests/YDotNet.Tests.Unit/Texts/ChunksTests.cs @@ -46,7 +46,6 @@ public void ChunksFormattedAtBeginning() Assert.That(firstChunk.Attributes.Count(), Is.EqualTo(expected: 1)); Assert.That(firstChunkAttribute.Key, Is.EqualTo("bold")); Assert.That(firstChunkAttribute.Value.Boolean, Is.True); - Assert.That(firstChunkAttribute.Value.String, Is.Null); var secondChunk = chunks.ElementAt(index: 1); @@ -78,7 +77,6 @@ public void ChunksFormattedAtMiddle() Assert.That(secondChunk.Attributes.Count(), Is.EqualTo(expected: 1)); Assert.That(secondChunkAttribute.Key, Is.EqualTo("bold")); Assert.That(secondChunkAttribute.Value.Boolean, Is.True); - Assert.That(secondChunkAttribute.Value.String, Is.Null); var thirdChunk = chunks.ElementAt(index: 2); @@ -110,7 +108,6 @@ public void ChunksFormattedAtEnding() Assert.That(secondChunk.Attributes.Count(), Is.EqualTo(expected: 1)); Assert.That(secondChunkAttribute.Key, Is.EqualTo("bold")); Assert.That(secondChunkAttribute.Value.Boolean, Is.True); - Assert.That(secondChunkAttribute.Value.String, Is.Null); } private (Text, Transaction) ArrangeText(uint index, uint length) diff --git a/Tests/YDotNet.Tests.Unit/Texts/InsertEmbedTests.cs b/Tests/YDotNet.Tests.Unit/Texts/InsertEmbedTests.cs index 071e812c..9cc46dfb 100644 --- a/Tests/YDotNet.Tests.Unit/Texts/InsertEmbedTests.cs +++ b/Tests/YDotNet.Tests.Unit/Texts/InsertEmbedTests.cs @@ -22,7 +22,6 @@ public void InsertBooleanEmbed() Assert.That(chunks.Length, Is.EqualTo(expected: 3)); Assert.That(chunks.ElementAt(index: 1).Data.Boolean, Is.True); - Assert.That(chunks.ElementAt(index: 1).Data.Long, Is.Null); } [Test] @@ -39,7 +38,6 @@ public void InsertDoubleEmbed() Assert.That(chunks.Length, Is.EqualTo(expected: 3)); Assert.That(chunks.ElementAt(index: 1).Data.Double, Is.EqualTo(expected: 24.69)); - Assert.That(chunks.ElementAt(index: 1).Data.Long, Is.Null); } [Test] @@ -56,7 +54,6 @@ public void InsertLongEmbed() Assert.That(chunks.Length, Is.EqualTo(expected: 3)); Assert.That(chunks.ElementAt(index: 1).Data.Long, Is.EqualTo(expected: 2469)); - Assert.That(chunks.ElementAt(index: 1).Data.Double, Is.Null); } [Test] @@ -73,7 +70,6 @@ public void InsertStringEmbed() Assert.That(chunks.Length, Is.EqualTo(expected: 3)); Assert.That(chunks.ElementAt(index: 1).Data.String, Is.EqualTo("Between")); - Assert.That(chunks.ElementAt(index: 1).Data.Long, Is.Null); } [Test] @@ -90,7 +86,6 @@ public void InsertBytesEmbed() Assert.That(chunks.Length, Is.EqualTo(expected: 3)); Assert.That(chunks.ElementAt(index: 1).Data.Bytes, Is.EqualTo(new byte[] { 2, 4, 6, 9 })); - Assert.That(chunks.ElementAt(index: 1).Data.Long, Is.Null); } [Test] @@ -113,7 +108,6 @@ public void InsertCollectionEmbed() Assert.That(chunks.Length, Is.EqualTo(expected: 3)); Assert.That(chunks.ElementAt(index: 1).Data.Collection.Length, Is.EqualTo(expected: 2)); - Assert.That(chunks.ElementAt(index: 1).Data.Long, Is.Null); } [Test] @@ -138,8 +132,6 @@ public void InsertObjectEmbed() Assert.That(secondChunk.Count, Is.EqualTo(expected: 1)); Assert.That(secondChunk.Keys.First(), Is.EqualTo("italics")); Assert.That(secondChunk.Values.First().Boolean, Is.True); - Assert.That(secondChunk.Values.First().Long, Is.Null); - Assert.That(chunks.ElementAt(index: 1).Data.Long, Is.Null); } [Test] @@ -156,7 +148,6 @@ public void InsertNullEmbed() Assert.That(chunks.Length, Is.EqualTo(expected: 3)); Assert.That(chunks.ElementAt(index: 1).Data.Null, Is.True); - Assert.That(chunks.ElementAt(index: 1).Data.Long, Is.Null); } [Test] @@ -173,7 +164,6 @@ public void InsertUndefinedEmbed() Assert.That(chunks.Length, Is.EqualTo(expected: 3)); Assert.That(chunks.ElementAt(index: 1).Data.Undefined, Is.True); - Assert.That(chunks.ElementAt(index: 1).Data.Long, Is.Null); } [Test] @@ -194,11 +184,9 @@ public void InsertBooleanEmbedWithAttributes() Assert.That(chunks.Length, Is.EqualTo(expected: 3)); Assert.That(chunks.ElementAt(index: 1).Data.Boolean, Is.True); - Assert.That(chunks.ElementAt(index: 1).Data.Long, Is.Null); Assert.That(chunks.ElementAt(index: 1).Attributes.Count(), Is.EqualTo(expected: 1)); Assert.That(chunks.ElementAt(index: 1).Attributes.First().Key, Is.EqualTo("bold")); Assert.That(chunks.ElementAt(index: 1).Attributes.First().Value.Boolean, Is.True); - Assert.That(chunks.ElementAt(index: 1).Attributes.First().Value.Long, Is.Null); } private (Text, Transaction) ArrangeText() diff --git a/Tests/YDotNet.Tests.Unit/Texts/ObserveTests.cs b/Tests/YDotNet.Tests.Unit/Texts/ObserveTests.cs index 4b016978..21ab6290 100644 --- a/Tests/YDotNet.Tests.Unit/Texts/ObserveTests.cs +++ b/Tests/YDotNet.Tests.Unit/Texts/ObserveTests.cs @@ -137,6 +137,5 @@ public void ObserveHasDeltasWhenAddedWithAttributes() Assert.That(eventDeltas.First().Attributes.Count(), Is.EqualTo(expected: 1)); Assert.That(eventDeltas.First().Attributes.First().Key, Is.EqualTo("bold")); Assert.That(eventDeltas.First().Attributes.First().Value.Boolean, Is.True); - Assert.That(eventDeltas.First().Attributes.First().Value.Long, Is.Null); } } diff --git a/Tests/YDotNet.Tests.Unit/UndoManagers/RedoTests.cs b/Tests/YDotNet.Tests.Unit/UndoManagers/RedoTests.cs index 11b1ecd5..c0d822f3 100644 --- a/Tests/YDotNet.Tests.Unit/UndoManagers/RedoTests.cs +++ b/Tests/YDotNet.Tests.Unit/UndoManagers/RedoTests.cs @@ -66,7 +66,7 @@ public void RedoAddingAndUpdatingAndRemovingContentOnText() // Assert Assert.That(chunks.Length, Is.EqualTo(expected: 3)); - Assert.That(result, Is.True); + Assert.That(result, Is.False); // Act (remove, undo, and redo) transaction = doc.WriteTransaction(); @@ -171,7 +171,6 @@ public void RedoAddingAndUpdatingAndRemovingContentOnMap() // Assert Assert.That(length, Is.EqualTo(expected: 4)); Assert.That(value2.Undefined, Is.True); - Assert.That(value2.String, Is.Null); Assert.That(result, Is.True); // Act (remove, undo, and redo) diff --git a/Tests/YDotNet.Tests.Unit/UndoManagers/UndoTests.cs b/Tests/YDotNet.Tests.Unit/UndoManagers/UndoTests.cs index a7bbc23c..593c8f27 100644 --- a/Tests/YDotNet.Tests.Unit/UndoManagers/UndoTests.cs +++ b/Tests/YDotNet.Tests.Unit/UndoManagers/UndoTests.cs @@ -82,6 +82,7 @@ public void UndoAddingAndUpdatingAndRemovingContentOnText() } [Test] + [Ignore("There seems to be a bug in y-crdt.")] public void UndoAddingAndUpdatingAndRemovingContentOnArray() { // Arrange @@ -181,7 +182,6 @@ public void UndoAddingAndUpdatingAndRemovingContentOnMap() // Assert Assert.That(length, Is.EqualTo(expected: 3)); Assert.That(value1.Long, Is.EqualTo(expected: 2469L)); - Assert.That(value1.String, Is.Null); Assert.That(result, Is.True); } diff --git a/Tests/YDotNet.Tests.Unit/XmlElements/FirstChildTests.cs b/Tests/YDotNet.Tests.Unit/XmlElements/FirstChildTests.cs index 4d5190a7..176b96bd 100644 --- a/Tests/YDotNet.Tests.Unit/XmlElements/FirstChildTests.cs +++ b/Tests/YDotNet.Tests.Unit/XmlElements/FirstChildTests.cs @@ -40,7 +40,6 @@ public void FirstChildOfRootFilledNodeIsCorrect() transaction.Commit(); // Assert - Assert.That(childXmlElement.XmlElement, Is.Null); Assert.That(childXmlElement.XmlText, Is.Not.Null); } @@ -86,6 +85,5 @@ public void FirstChildOfNestedFilledNodeIsCorrect() // Assert Assert.That(grandChildXmlElement.XmlElement, Is.Not.Null); - Assert.That(grandChildXmlElement.XmlText, Is.Null); } } diff --git a/Tests/YDotNet.Tests.Unit/XmlElements/GetTests.cs b/Tests/YDotNet.Tests.Unit/XmlElements/GetTests.cs index 79c414f4..c0266885 100644 --- a/Tests/YDotNet.Tests.Unit/XmlElements/GetTests.cs +++ b/Tests/YDotNet.Tests.Unit/XmlElements/GetTests.cs @@ -34,7 +34,6 @@ public void GetXmlText() transaction.Commit(); // Assert - Assert.That(output.XmlElement, Is.Null); Assert.That(output.XmlText, Is.Not.Null); } @@ -51,7 +50,6 @@ public void GetXmlElement() // Assert Assert.That(output.XmlElement, Is.Not.Null); - Assert.That(output.XmlText, Is.Null); } private (Doc, XmlElement) ArrangeDoc() diff --git a/Tests/YDotNet.Tests.Unit/XmlElements/NextSiblingTests.cs b/Tests/YDotNet.Tests.Unit/XmlElements/NextSiblingTests.cs index 4a47ba2c..a0a9d9b5 100644 --- a/Tests/YDotNet.Tests.Unit/XmlElements/NextSiblingTests.cs +++ b/Tests/YDotNet.Tests.Unit/XmlElements/NextSiblingTests.cs @@ -19,7 +19,6 @@ public void GetsNextSiblingAtBeginning() transaction.Commit(); // Assert - Assert.That(sibling.XmlElement, Is.Null); Assert.That(sibling.XmlText, Is.Not.Null); } @@ -36,7 +35,6 @@ public void GetsNextSiblingAtMiddle() transaction.Commit(); // Assert - Assert.That(sibling.XmlElement, Is.Null); Assert.That(sibling.XmlText, Is.Not.Null); } diff --git a/Tests/YDotNet.Tests.Unit/XmlElements/ObserveTests.cs b/Tests/YDotNet.Tests.Unit/XmlElements/ObserveTests.cs index e59db56e..c3130054 100644 --- a/Tests/YDotNet.Tests.Unit/XmlElements/ObserveTests.cs +++ b/Tests/YDotNet.Tests.Unit/XmlElements/ObserveTests.cs @@ -50,12 +50,9 @@ public void ObserveHasDeltaWhenAddedXmlElementsAndTexts() Assert.That(eventChanges.First().Tag, Is.EqualTo(EventChangeTag.Add)); Assert.That(eventChanges.First().Length, Is.EqualTo(expected: 3)); Assert.That(eventChanges.First().Values.ElementAt(index: 0).XmlText, Is.Not.Null); - Assert.That(eventChanges.First().Values.ElementAt(index: 0).XmlElement, Is.Null); - Assert.That(eventChanges.First().Values.ElementAt(index: 1).XmlText, Is.Null); Assert.That(eventChanges.First().Values.ElementAt(index: 1).XmlElement, Is.Not.Null); Assert.That(eventChanges.First().Values.ElementAt(index: 1).XmlElement.Tag, Is.EqualTo("color")); Assert.That(eventChanges.First().Values.ElementAt(index: 2).XmlText, Is.Not.Null); - Assert.That(eventChanges.First().Values.ElementAt(index: 2).XmlElement, Is.Null); } [Test] @@ -106,11 +103,8 @@ public void ObserveHasKeysWhenAddedAttributes() var asChange = keyChanges.Single(x => x.Key == "as"); Assert.That(hrefChange.NewValue.String, Is.EqualTo("https://lsviana.github.io/")); - Assert.That(hrefChange.NewValue.Long, Is.Null); Assert.That(relChange.NewValue.String, Is.EqualTo("preload")); - Assert.That(relChange.NewValue.Long, Is.Null); Assert.That(asChange.NewValue.String, Is.EqualTo("document")); - Assert.That(asChange.NewValue.Long, Is.Null); } [Test] @@ -138,9 +132,7 @@ public void ObserveHasKeysWhenUpdatedAttributes() Assert.That(keyChanges.ElementAt(index: 0).Tag, Is.EqualTo(EventKeyChangeTag.Update)); Assert.That(keyChanges.ElementAt(index: 0).Key, Is.EqualTo("href")); Assert.That(keyChanges.ElementAt(index: 0).NewValue.String, Is.EqualTo("https://github.com/LSViana/y-crdt")); - Assert.That(keyChanges.ElementAt(index: 0).NewValue.Long, Is.Null); Assert.That(keyChanges.ElementAt(index: 0).OldValue.String, Is.EqualTo("https://lsviana.github.io/")); - Assert.That(keyChanges.ElementAt(index: 0).OldValue.Long, Is.Null); } [Test] @@ -167,9 +159,7 @@ public void ObserveHasKeysWhenRemovedAttributes() Assert.That(keyChanges.Count(), Is.EqualTo(expected: 1)); Assert.That(keyChanges.ElementAt(index: 0).Tag, Is.EqualTo(EventKeyChangeTag.Remove)); Assert.That(keyChanges.ElementAt(index: 0).Key, Is.EqualTo("href")); - Assert.That(keyChanges.ElementAt(index: 0).NewValue, Is.Null); Assert.That(keyChanges.ElementAt(index: 0).OldValue.String, Is.EqualTo("https://lsviana.github.io/")); - Assert.That(keyChanges.ElementAt(index: 0).OldValue.Long, Is.Null); } [Test] diff --git a/Tests/YDotNet.Tests.Unit/XmlElements/PreviousSiblingTests.cs b/Tests/YDotNet.Tests.Unit/XmlElements/PreviousSiblingTests.cs index 6eaec847..837348cf 100644 --- a/Tests/YDotNet.Tests.Unit/XmlElements/PreviousSiblingTests.cs +++ b/Tests/YDotNet.Tests.Unit/XmlElements/PreviousSiblingTests.cs @@ -35,7 +35,6 @@ public void GetsPreviousSiblingAtMiddle() transaction.Commit(); // Assert - Assert.That(sibling.XmlElement, Is.Null); Assert.That(sibling.XmlText, Is.Not.Null); } @@ -52,7 +51,6 @@ public void GetsPreviousSiblingAtEnding() transaction.Commit(); // Assert - Assert.That(sibling.XmlElement, Is.Null); Assert.That(sibling.XmlText, Is.Not.Null); } diff --git a/Tests/YDotNet.Tests.Unit/XmlElements/TreeWalkerTests.cs b/Tests/YDotNet.Tests.Unit/XmlElements/TreeWalkerTests.cs index 980bbb52..2d40c025 100644 --- a/Tests/YDotNet.Tests.Unit/XmlElements/TreeWalkerTests.cs +++ b/Tests/YDotNet.Tests.Unit/XmlElements/TreeWalkerTests.cs @@ -46,12 +46,9 @@ public void WalksOnTreeWithSingleLevelOfDepth() Assert.That(xmlTreeWalker, Is.Not.Null); Assert.That(xmlNodes.Length, Is.EqualTo(expected: 3)); Assert.That(xmlNodes.ElementAt(index: 0).XmlText, Is.Not.Null); - Assert.That(xmlNodes.ElementAt(index: 0).XmlElement, Is.Null); - Assert.That(xmlNodes.ElementAt(index: 1).XmlText, Is.Null); Assert.That(xmlNodes.ElementAt(index: 1).XmlElement, Is.Not.Null); Assert.That(xmlNodes.ElementAt(index: 1).XmlElement.Tag, Is.EqualTo("color")); Assert.That(xmlNodes.ElementAt(index: 2).XmlText, Is.Not.Null); - Assert.That(xmlNodes.ElementAt(index: 2).XmlElement, Is.Null); } [Test] @@ -81,17 +78,12 @@ public void WalksOnTreeWithMultipleLevelsOfDepth() Assert.That(xmlTreeWalker, Is.Not.Null); Assert.That(xmlNodes.Length, Is.EqualTo(expected: 5)); Assert.That(xmlNodes.ElementAt(index: 0).XmlText, Is.Not.Null); - Assert.That(xmlNodes.ElementAt(index: 0).XmlElement, Is.Null); - Assert.That(xmlNodes.ElementAt(index: 1).XmlText, Is.Null); Assert.That(xmlNodes.ElementAt(index: 1).XmlElement, Is.Not.Null); Assert.That(xmlNodes.ElementAt(index: 1).XmlElement.Tag, Is.EqualTo("color")); - Assert.That(xmlNodes.ElementAt(index: 2).XmlText, Is.Null); Assert.That(xmlNodes.ElementAt(index: 2).XmlElement, Is.Not.Null); Assert.That(xmlNodes.ElementAt(index: 2).XmlElement.Tag, Is.EqualTo("alpha")); - Assert.That(xmlNodes.ElementAt(index: 3).XmlText, Is.Null); Assert.That(xmlNodes.ElementAt(index: 3).XmlElement, Is.Not.Null); Assert.That(xmlNodes.ElementAt(index: 3).XmlElement.Tag, Is.EqualTo("hex")); Assert.That(xmlNodes.ElementAt(index: 4).XmlText, Is.Not.Null); - Assert.That(xmlNodes.ElementAt(index: 4).XmlElement, Is.Null); } } diff --git a/Tests/YDotNet.Tests.Unit/XmlTexts/NextSiblingTests.cs b/Tests/YDotNet.Tests.Unit/XmlTexts/NextSiblingTests.cs index c5655b95..46e52bec 100644 --- a/Tests/YDotNet.Tests.Unit/XmlTexts/NextSiblingTests.cs +++ b/Tests/YDotNet.Tests.Unit/XmlTexts/NextSiblingTests.cs @@ -20,7 +20,6 @@ public void GetsNextSiblingAtBeginning() // Assert Assert.That(sibling.XmlElement, Is.Not.Null); - Assert.That(sibling.XmlText, Is.Null); } [Test] @@ -37,7 +36,6 @@ public void GetsNextSiblingAtMiddle() // Assert Assert.That(sibling.XmlElement, Is.Not.Null); - Assert.That(sibling.XmlText, Is.Null); } [Test] diff --git a/Tests/YDotNet.Tests.Unit/XmlTexts/ObserveTests.cs b/Tests/YDotNet.Tests.Unit/XmlTexts/ObserveTests.cs index 80335a08..df1484ea 100644 --- a/Tests/YDotNet.Tests.Unit/XmlTexts/ObserveTests.cs +++ b/Tests/YDotNet.Tests.Unit/XmlTexts/ObserveTests.cs @@ -61,20 +61,16 @@ public void ObserveHasDeltaWhenAddedTextsAndEmbeds() Assert.That(firstDelta.Length, Is.EqualTo(expected: 1)); Assert.That(firstDelta.Insert.String, Is.EqualTo("Luc")); - Assert.That(firstDelta.Insert.Long, Is.Null); Assert.That(firstDelta.Attributes, Is.Empty); Assert.That(secondDelta.Length, Is.EqualTo(expected: 1)); Assert.That(secondDelta.Insert.Boolean, Is.EqualTo(expected: true)); - Assert.That(secondDelta.Insert.String, Is.Null); Assert.That(secondDelta.Attributes.Count(), Is.EqualTo(expected: 1)); Assert.That(secondDelta.Attributes.ElementAt(index: 0).Key, Is.EqualTo("bold")); Assert.That(secondDelta.Attributes.ElementAt(index: 0).Value.Boolean, Is.True); - Assert.That(secondDelta.Attributes.ElementAt(index: 0).Value.Long, Is.Null); Assert.That(thirdDelta.Length, Is.EqualTo(expected: 1)); Assert.That(thirdDelta.Insert.String, Is.EqualTo("as")); - Assert.That(thirdDelta.Insert.Long, Is.Null); Assert.That(thirdDelta.Attributes, Is.Empty); } diff --git a/Tests/YDotNet.Tests.Unit/XmlTexts/PreviousSiblingTests.cs b/Tests/YDotNet.Tests.Unit/XmlTexts/PreviousSiblingTests.cs index d7d9ef7a..92e37ee5 100644 --- a/Tests/YDotNet.Tests.Unit/XmlTexts/PreviousSiblingTests.cs +++ b/Tests/YDotNet.Tests.Unit/XmlTexts/PreviousSiblingTests.cs @@ -36,7 +36,6 @@ public void GetsPreviousSiblingAtMiddle() // Assert Assert.That(sibling.XmlElement, Is.Not.Null); - Assert.That(sibling.XmlText, Is.Null); } [Test] @@ -53,7 +52,6 @@ public void GetsPreviousSiblingAtEnding() // Assert Assert.That(sibling.XmlElement, Is.Not.Null); - Assert.That(sibling.XmlText, Is.Null); } private (Doc, XmlElement) ArrangeDoc() diff --git a/YDotNet.sln b/YDotNet.sln index 0de44951..9eb4eaa1 100644 --- a/YDotNet.sln +++ b/YDotNet.sln @@ -1,9 +1,23 @@ -Microsoft Visual Studio Solution File, Format Version 12.00 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "YDotNet", "YDotNet\YDotNet.csproj", "{52763429-AB26-4415-9C7B-F17012FE3FDA}" + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.4.33103.184 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "YDotNet", "YDotNet\YDotNet.csproj", "{52763429-AB26-4415-9C7B-F17012FE3FDA}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{03858045-3849-41E2-ACE9-F10AAA4CCBCA}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "YDotNet.Tests.Unit", "Tests\YDotNet.Tests.Unit\YDotNet.Tests.Unit.csproj", "{F85C9334-87AF-4FFC-A301-3A9F57ECD4AB}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "YDotNet.Tests.Unit", "Tests\YDotNet.Tests.Unit\YDotNet.Tests.Unit.csproj", "{F85C9334-87AF-4FFC-A301-3A9F57ECD4AB}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Native", "Native", "{95BDA0A4-331B-4357-B368-A784B66F19AD}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "YDotNet.Native.Win32", "native\YDotNet.Native.Win32\YDotNet.Native.Win32.csproj", "{9E2E0844-F7BC-4CE5-A861-E6D719D1B3A0}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "YDotNet.Native.Linux", "native\YDotNet.Native.Linux\YDotNet.Native.Linux.csproj", "{5F9B181A-773F-40E9-ACAD-40AE7ABB1D8C}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "YDotNet.Native.MacOS", "native\YDotNet.Native.MacOS\YDotNet.Native.MacOS.csproj", "{D93CE5FA-9C04-420A-9635-81F4E4C092D0}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "YDotNet.Native", "native\YDotNet.Native\YDotNet.Native.csproj", "{95D7DB70-2794-44FF-A196-BBD0FC3988A6}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -19,8 +33,34 @@ Global {F85C9334-87AF-4FFC-A301-3A9F57ECD4AB}.Debug|Any CPU.Build.0 = Debug|Any CPU {F85C9334-87AF-4FFC-A301-3A9F57ECD4AB}.Release|Any CPU.ActiveCfg = Debug|Any CPU {F85C9334-87AF-4FFC-A301-3A9F57ECD4AB}.Release|Any CPU.Build.0 = Debug|Any CPU + {9E2E0844-F7BC-4CE5-A861-E6D719D1B3A0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {9E2E0844-F7BC-4CE5-A861-E6D719D1B3A0}.Debug|Any CPU.Build.0 = Debug|Any CPU + {9E2E0844-F7BC-4CE5-A861-E6D719D1B3A0}.Release|Any CPU.ActiveCfg = Release|Any CPU + {9E2E0844-F7BC-4CE5-A861-E6D719D1B3A0}.Release|Any CPU.Build.0 = Release|Any CPU + {5F9B181A-773F-40E9-ACAD-40AE7ABB1D8C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {5F9B181A-773F-40E9-ACAD-40AE7ABB1D8C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {5F9B181A-773F-40E9-ACAD-40AE7ABB1D8C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {5F9B181A-773F-40E9-ACAD-40AE7ABB1D8C}.Release|Any CPU.Build.0 = Release|Any CPU + {D93CE5FA-9C04-420A-9635-81F4E4C092D0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D93CE5FA-9C04-420A-9635-81F4E4C092D0}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D93CE5FA-9C04-420A-9635-81F4E4C092D0}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D93CE5FA-9C04-420A-9635-81F4E4C092D0}.Release|Any CPU.Build.0 = Release|Any CPU + {95D7DB70-2794-44FF-A196-BBD0FC3988A6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {95D7DB70-2794-44FF-A196-BBD0FC3988A6}.Debug|Any CPU.Build.0 = Debug|Any CPU + {95D7DB70-2794-44FF-A196-BBD0FC3988A6}.Release|Any CPU.ActiveCfg = Release|Any CPU + {95D7DB70-2794-44FF-A196-BBD0FC3988A6}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE EndGlobalSection GlobalSection(NestedProjects) = preSolution {F85C9334-87AF-4FFC-A301-3A9F57ECD4AB} = {03858045-3849-41E2-ACE9-F10AAA4CCBCA} + {9E2E0844-F7BC-4CE5-A861-E6D719D1B3A0} = {95BDA0A4-331B-4357-B368-A784B66F19AD} + {5F9B181A-773F-40E9-ACAD-40AE7ABB1D8C} = {95BDA0A4-331B-4357-B368-A784B66F19AD} + {D93CE5FA-9C04-420A-9635-81F4E4C092D0} = {95BDA0A4-331B-4357-B368-A784B66F19AD} + {95D7DB70-2794-44FF-A196-BBD0FC3988A6} = {95BDA0A4-331B-4357-B368-A784B66F19AD} + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {F7865083-8AF3-4562-88F2-95FD43368B57} EndGlobalSection EndGlobal diff --git a/YDotNet/Document/Cells/Input.cs b/YDotNet/Document/Cells/Input.cs index d64cc30a..9a89a5d0 100644 --- a/YDotNet/Document/Cells/Input.cs +++ b/YDotNet/Document/Cells/Input.cs @@ -11,7 +11,7 @@ public abstract class Input : IDisposable /// /// Gets or sets the native input cell represented by this cell. /// - internal InputNative InputNative { get; set; } + public InputNative InputNative { get; set; } /// public abstract void Dispose(); diff --git a/YDotNet/Document/Cells/Output.cs b/YDotNet/Document/Cells/Output.cs index b538b303..d64eb04b 100644 --- a/YDotNet/Document/Cells/Output.cs +++ b/YDotNet/Document/Cells/Output.cs @@ -1,3 +1,5 @@ +using System.Formats.Asn1; +using System.Reflection.Metadata; using System.Runtime.InteropServices; using YDotNet.Document.Types.Maps; using YDotNet.Document.Types.Texts; @@ -45,6 +47,8 @@ public string? String { get { + EnsureType(OutputInputType.String); + MemoryReader.TryReadUtf8String(OutputChannel.String(Handle), out var result); return result; @@ -58,9 +62,16 @@ public bool? Boolean { get { + EnsureType(OutputInputType.Bool); + var value = OutputChannel.Boolean(Handle); - return value == nint.Zero ? null : Marshal.PtrToStructure(value) == 1; + if (value == nint.Zero) + { + throw new InvalidOperationException("Internal type mismatch, native library returns null."); + } + + return Marshal.PtrToStructure(value) == 1; } } @@ -71,9 +82,16 @@ public double? Double { get { + EnsureType(OutputInputType.Double); + var value = OutputChannel.Double(Handle); - return value == nint.Zero ? null : Marshal.PtrToStructure(value); + if (value == nint.Zero) + { + throw new InvalidOperationException("Internal type mismatch, native library returns null."); + } + + return Marshal.PtrToStructure(value); } } @@ -84,25 +102,60 @@ public long? Long { get { + EnsureType(OutputInputType.Long); + var value = OutputChannel.Long(Handle); - return value == nint.Zero ? null : Marshal.PtrToStructure(value); + if (value == nint.Zero) + { + throw new InvalidOperationException("Internal type mismatch, native library returns null."); + } + + return Marshal.PtrToStructure(value); } } /// /// Gets the array or null if this output cells contains a different type stored. /// - public byte[]? Bytes => MemoryReader.TryReadBytes(OutputChannel.Bytes(Handle), OutputNative.Value.Length); + public byte[] Bytes + { + get + { + EnsureType(OutputInputType.Bytes); + + var result = MemoryReader.TryReadBytes(OutputChannel.Bytes(Handle), OutputNative.Value.Length) ?? + throw new InvalidOperationException("Internal type mismatch, native library returns null."); + + if (result == null) + { + throw new InvalidOperationException("Internal type mismatch, native library returns null."); + } + + return result; + } + } /// /// Gets the collection or null if this output cells contains a different type stored. /// - public Output[]? Collection => - MemoryReader.TryReadIntPtrArray( - OutputChannel.Collection(Handle), OutputNative.Value.Length, Marshal.SizeOf()) - ?.Select(x => new Output(x)) - .ToArray(); + public Output[] Collection + { + get + { + EnsureType(OutputInputType.Collection); + + var handles = MemoryReader.TryReadIntPtrArray( + OutputChannel.Collection(Handle), OutputNative!.Value.Length, Marshal.SizeOf()); + + if (handles == null) + { + throw new InvalidOperationException("Internal type mismatch, native library returns null."); + } + + return handles.Select(x => new Output(x)).ToArray(); + } + } /// /// Gets the dictionary or null if this output cells contains a different type stored. @@ -111,12 +164,14 @@ public IDictionary? Object { get { + EnsureType(OutputInputType.Object); + var handles = MemoryReader.TryReadIntPtrArray( - OutputChannel.Object(Handle), OutputNative.Value.Length, Marshal.SizeOf()); + OutputChannel.Object(Handle), OutputNative!.Value.Length, Marshal.SizeOf()); if (handles == null) { - return null; + throw new InvalidOperationException("Internal type mismatch, native library returns null."); } var result = new Dictionary(); @@ -136,42 +191,92 @@ public IDictionary? Object /// /// Gets a value indicating whether this output cell contains a null value. /// - public bool Null => OutputChannel.Null(Handle) == 1; + public bool Null => Type == OutputInputType.Null; /// /// Gets a value indicating whether this output cell contains an undefined value. /// - public bool Undefined => OutputChannel.Undefined(Handle) == 1; + public bool Undefined => Type == OutputInputType.Undefined; /// /// Gets the or null if this output cells contains a different type stored. /// - public Array? Array => ReferenceAccessor.Access(new Array(OutputChannel.Array(Handle))); + public Array Array + { + get + { + EnsureType(OutputInputType.Array); + + return ReferenceAccessor.Access(new Array(OutputChannel.Array(Handle))) ?? + throw new InvalidOperationException("Internal type mismatch, native library returns null."); + } + } /// /// Gets the or null if this output cells contains a different /// type stored. /// - public Map? Map => ReferenceAccessor.Access(new Map(OutputChannel.Map(Handle))); + public Map Map + { + get + { + EnsureType(OutputInputType.Map); + + return ReferenceAccessor.Access(new Map(OutputChannel.Map(Handle))) ?? + throw new InvalidOperationException("Internal type mismatch, native library returns null."); + } + } /// /// Gets the or null if this output cells contains a different /// type /// stored. /// - public Text? Text => ReferenceAccessor.Access(new Text(OutputChannel.Text(Handle))); + public Text Text + { + get + { + EnsureType(OutputInputType.Text); + + return ReferenceAccessor.Access(new Text(OutputChannel.Text(Handle))) ?? + throw new InvalidOperationException("Internal type mismatch, native library returns null."); + } + } /// /// Gets the or null if this output cells contains /// a different type stored. /// - public XmlElement? XmlElement => ReferenceAccessor.Access(new XmlElement(OutputChannel.XmlElement(Handle))); + public XmlElement XmlElement + { + get + { + EnsureType(OutputInputType.XmlElement); + + return ReferenceAccessor.Access(new XmlElement(OutputChannel.XmlElement(Handle))) ?? + throw new InvalidOperationException("Internal type mismatch, native library returns null."); + } + } /// /// Gets the or null if this output cells contains a /// different type stored. /// - public XmlText? XmlText => ReferenceAccessor.Access(new XmlText(OutputChannel.XmlText(Handle))); + public XmlText? XmlText + { + get + { + EnsureType(OutputInputType.XmlText); + + return ReferenceAccessor.Access(new XmlText(OutputChannel.XmlText(Handle))) ?? + throw new InvalidOperationException("Internal type mismatch, native library returns null."); + } + } + + /// + /// Gets the type of the output. + /// + public OutputInputType Type => (OutputInputType)(OutputNative?.Tag ?? -99); /// /// Gets the handle to the native resource. @@ -183,6 +288,14 @@ public IDictionary? Object /// private OutputNative? OutputNative { get; } + private void EnsureType(OutputInputType expectedType) + { + if (Type != expectedType) + { + throw new InvalidOperationException($"Expected {expectedType}, got {Type}."); + } + } + /// public void Dispose() { diff --git a/YDotNet/Document/Cells/OutputInputType.cs b/YDotNet/Document/Cells/OutputInputType.cs new file mode 100644 index 00000000..28f372bb --- /dev/null +++ b/YDotNet/Document/Cells/OutputInputType.cs @@ -0,0 +1,92 @@ +namespace YDotNet.Document.Cells; + +/// +/// The type of an output. +/// +public enum OutputInputType +{ + /// + /// No defined. + /// + NotSet = -99, + + /// + /// Flag used by `YInput` and `YOutput` to tag boolean values. + /// + Bool = -8, + + /// + /// Flag used by `YInput` and `YOutput` to tag floating point numbers. + /// + Double = -7, + + /// + /// Flag used by `YInput` and `YOutput` to tag 64-bit integer numbers. + /// + Long = -6, + + /// + /// Flag used by `YInput` and `YOutput` to tag strings. + /// + String = -5, + + /// + /// Flag used by `YInput` and `YOutput` to tag binary content. + /// + Bytes = -4, + + /// + /// Flag used by `YInput` and `YOutput` to tag embedded JSON-like arrays of values. + /// + Collection = -3, + + /// + /// Flag used by `YInput` and `YOutput` to tag embedded JSON-like maps of key-value pairs. + /// + Object = -2, + + /// + /// Flag used by `YInput` and `YOutput` to tag JSON-like null values. + /// + Null = -1, + + /// + /// Flag used by `YInput` and `YOutput` to tag JSON-like undefined values. + /// + Undefined = 0, + + /// + /// Flag used by `YInput` and `YOutput` to tag content, which is an `YArray` shared type. + /// + Array = 1, + + /// + /// Flag used by `YInput` and `YOutput` to tag content, which is an `YMap` shared type. + /// + Map = 2, + + /// + /// Flag used by `YInput` and `YOutput` to tag content, which is an `YText` shared type. + /// + Text = 3, + + /// + /// Flag used by `YInput` and `YOutput` to tag content, which is an `YXmlElement` shared type. + /// + XmlElement = 4, + + /// + /// Flag used by `YInput` and `YOutput` to tag content, which is an `YXmlText` shared type. + /// + XmlText = 5, + + /// + /// Flag used by `YInput` and `YOutput` to tag content, which is an `YXmlFragment` shared type. + /// + XmlFragment = 6, + + /// + /// Flag used by `YInput` and `YOutput` to tag content, which is an `YDoc` shared type. + /// + Doc = 7 +} diff --git a/YDotNet/Document/Options/DocOptions.cs b/YDotNet/Document/Options/DocOptions.cs index 36b68008..508eb2db 100644 --- a/YDotNet/Document/Options/DocOptions.cs +++ b/YDotNet/Document/Options/DocOptions.cs @@ -1,4 +1,4 @@ -namespace YDotNet.Document.Options; +namespace YDotNet.Document.Options; /// /// Configuration object that, optionally, is used to create instances. @@ -10,7 +10,7 @@ public class DocOptions /// internal static DocOptions Default => new() { - Id = (ulong) Random.Shared.NextInt64(), + Id = (ulong) Random.Shared.Next(), ShouldLoad = true, Encoding = DocEncoding.Utf16 }; diff --git a/YDotNet/Document/Transactions/Transaction.cs b/YDotNet/Document/Transactions/Transaction.cs index a68e97ba..abe4f98d 100644 --- a/YDotNet/Document/Transactions/Transaction.cs +++ b/YDotNet/Document/Transactions/Transaction.cs @@ -127,7 +127,7 @@ public byte[] StateVectorV1() /// public byte[] StateDiffV1(byte[] stateVector) { - var handle = TransactionChannel.StateDiffV1(Handle, stateVector, (uint) stateVector.Length, out var length); + var handle = TransactionChannel.StateDiffV1(Handle, stateVector, (uint) (stateVector != null ? stateVector.Length : 0), out var length); var data = MemoryReader.ReadBytes(handle, length); BinaryChannel.Destroy(handle, length); diff --git a/YDotNet/Document/Types/Maps/Map.cs b/YDotNet/Document/Types/Maps/Map.cs index 0b8dcc4b..a4403fd0 100644 --- a/YDotNet/Document/Types/Maps/Map.cs +++ b/YDotNet/Document/Types/Maps/Map.cs @@ -35,10 +35,12 @@ internal Map(nint handle) public void Insert(Transaction transaction, string key, Input input) { var keyHandle = MemoryWriter.WriteUtf8String(key); + var valuePointer = MemoryWriter.WriteStruct(input.InputNative); - MapChannel.Insert(Handle, transaction.Handle, keyHandle, input.InputNative); + MapChannel.Insert(Handle, transaction.Handle, keyHandle, valuePointer); MemoryWriter.Release(keyHandle); + MemoryWriter.Release(valuePointer); } /// diff --git a/YDotNet/Native/Cells/Inputs/InputNative.cs b/YDotNet/Native/Cells/Inputs/InputNative.cs index bfafe83e..7ddf4b71 100644 --- a/YDotNet/Native/Cells/Inputs/InputNative.cs +++ b/YDotNet/Native/Cells/Inputs/InputNative.cs @@ -4,7 +4,7 @@ namespace YDotNet.Native.Cells.Inputs; // The size has to be 24 here so that the whole data of the input cell is written/read correctly over the C FFI. [StructLayout(LayoutKind.Explicit, Size = 24)] -internal struct InputNative +public struct InputNative { [field: FieldOffset(offset: 0)] public sbyte Tag { get; } diff --git a/YDotNet/Native/ChannelSettings.cs b/YDotNet/Native/ChannelSettings.cs index 2dc2eebf..4162b324 100644 --- a/YDotNet/Native/ChannelSettings.cs +++ b/YDotNet/Native/ChannelSettings.cs @@ -2,9 +2,6 @@ namespace YDotNet.Native; internal static class ChannelSettings { -#if WINDOWS - public const string NativeLib = "yrs.dll"; -#else - public const string NativeLib = "libyrs.dylib"; -#endif + // https://learn.microsoft.com/en-us/dotnet/standard/native-interop/native-library-loading + public const string NativeLib = "yrs"; } diff --git a/YDotNet/Native/Document/Events/AfterTransactionEventNative.cs b/YDotNet/Native/Document/Events/AfterTransactionEventNative.cs index 1e07b7fc..4fb92627 100644 --- a/YDotNet/Native/Document/Events/AfterTransactionEventNative.cs +++ b/YDotNet/Native/Document/Events/AfterTransactionEventNative.cs @@ -4,13 +4,16 @@ namespace YDotNet.Native.Document.Events; -[StructLayout(LayoutKind.Sequential)] +[StructLayout(LayoutKind.Explicit)] internal struct AfterTransactionEventNative { + [field: FieldOffset(0)] public StateVectorNative BeforeState { get; } + [field: FieldOffset(24)] public StateVectorNative AfterState { get; } + [field: FieldOffset(48)] public DeleteSetNative DeleteSet { get; } public AfterTransactionEvent ToAfterTransactionEvent() diff --git a/YDotNet/Native/Document/State/StateVectorNative.cs b/YDotNet/Native/Document/State/StateVectorNative.cs index 5db8137e..b83dbd29 100644 --- a/YDotNet/Native/Document/State/StateVectorNative.cs +++ b/YDotNet/Native/Document/State/StateVectorNative.cs @@ -3,13 +3,16 @@ namespace YDotNet.Native.Document.State; -[StructLayout(LayoutKind.Sequential)] +[StructLayout(LayoutKind.Explicit, Size = 24)] internal struct StateVectorNative { + [field: FieldOffset(0)] public uint EntriesCount { get; } + [field: FieldOffset(8)] public nint ClientIds { get; } + [field: FieldOffset(16)] public nint Clocks { get; } public StateVector ToStateVector() diff --git a/YDotNet/Native/Types/Maps/MapChannel.cs b/YDotNet/Native/Types/Maps/MapChannel.cs index 8bbde4f9..d35390eb 100644 --- a/YDotNet/Native/Types/Maps/MapChannel.cs +++ b/YDotNet/Native/Types/Maps/MapChannel.cs @@ -8,7 +8,7 @@ internal static class MapChannel public delegate void ObserveCallback(nint state, nint eventHandle); [DllImport(ChannelSettings.NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ymap_insert")] - public static extern void Insert(nint map, nint transaction, nint key, InputNative inputNative); + public static extern void Insert(nint map, nint transaction, nint key, nint value); [DllImport(ChannelSettings.NativeLib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ymap_get")] public static extern nint Get(nint map, nint transaction, nint key); diff --git a/YDotNet/stylecop.json b/YDotNet/stylecop.json new file mode 100644 index 00000000..42fb1f8e --- /dev/null +++ b/YDotNet/stylecop.json @@ -0,0 +1,14 @@ +{ + // ACTION REQUIRED: This file was automatically added to your project, but it + // will not take effect until additional steps are taken to enable it. See the + // following page for additional information: + // + // https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/EnableConfiguration.md + + "$schema": "https://raw.githubusercontent.com/DotNetAnalyzers/StyleCopAnalyzers/master/StyleCop.Analyzers/StyleCop.Analyzers/Settings/stylecop.schema.json", + "settings": { + "documentationRules": { + "companyName": "PlaceholderCompany" + } + } +} diff --git a/native/YDotNet.Native.Linux/YDotNet.Native.Linux.csproj b/native/YDotNet.Native.Linux/YDotNet.Native.Linux.csproj new file mode 100644 index 00000000..ddeadac2 --- /dev/null +++ b/native/YDotNet.Native.Linux/YDotNet.Native.Linux.csproj @@ -0,0 +1,18 @@ + + + + net7.0 + enable + enable + + + + + + + + + + + + diff --git a/native/YDotNet.Native.MacOS/YDotNet.Native.MacOS.csproj b/native/YDotNet.Native.MacOS/YDotNet.Native.MacOS.csproj new file mode 100644 index 00000000..f44615da --- /dev/null +++ b/native/YDotNet.Native.MacOS/YDotNet.Native.MacOS.csproj @@ -0,0 +1,13 @@ + + + + net7.0 + enable + enable + + + + + + + diff --git a/native/YDotNet.Native.Win32/YDotNet.Native.Win32.csproj b/native/YDotNet.Native.Win32/YDotNet.Native.Win32.csproj new file mode 100644 index 00000000..31220e5e --- /dev/null +++ b/native/YDotNet.Native.Win32/YDotNet.Native.Win32.csproj @@ -0,0 +1,13 @@ + + + + net7.0 + enable + enable + + + + + + + diff --git a/native/YDotNet.Native/YDotNet.Native.csproj b/native/YDotNet.Native/YDotNet.Native.csproj new file mode 100644 index 00000000..a51cb7c8 --- /dev/null +++ b/native/YDotNet.Native/YDotNet.Native.csproj @@ -0,0 +1,15 @@ + + + + net7.0 + enable + enable + + + + + + + + +