Search the source of every open source package.
231 results
global using Microsoft.VisualStudio.TestTools.UnitTesting;
[TestClass]
public class TestInit
{
[AssemblyInitialize]
public static void ClassInitialize( TestContext context )
{
Sandbox.Application.InitUnitTest();
}
}
using Sandbox;
[TestClass]
public partial class LibraryTests
{
[TestMethod]
public void SceneTest()
{
var scene = new Scene();
using ( scene.Push() )
{
var go = new GameObject();
Assert.AreEqual( 1, scene.Directory.GameObjectCount );
}
}
}
using Braxnet;
using Sandbox;
[TestClass]
public partial class LibraryTests
{
[TestMethod]
public void SceneTest()
{
var scene = new Scene();
using ( scene.Push() )
{
// var go = new GameObject();
Assert.AreEqual( 1, scene.Directory.GameObjectCount );
Assert.IsTrue( scene.Directory.FindByName( "LibraryTestComponent" ) != null );
}
}
}
[Autoload]
public class LibraryTestComponent : Component
{
}
using Sandbox;
[TestClass]
public partial class LibraryTests
{
[TestMethod]
public void SceneTest()
{
var scene = new Scene();
using ( scene.Push() )
{
var go = new GameObject();
Assert.AreEqual( 1, scene.Directory.GameObjectCount );
}
}
}
global using Microsoft.VisualStudio.TestTools.UnitTesting;
[TestClass]
public class TestInit
{
[AssemblyInitialize]
public static void ClassInitialize( TestContext context )
{
Sandbox.Application.InitUnitTest();
}
}
using Sandbox;
[TestClass]
public partial class LibraryTests
{
[TestMethod]
public void SceneTest()
{
var scene = new Scene();
using ( scene.Push() )
{
var go = new GameObject();
Assert.AreEqual( 1, scene.Directory.GameObjectCount );
}
}
}
using System;
using static TestClasses;
namespace SandbankDatabase;
internal static class TestData
{
public static ReadmeExample TestData1 = new ReadmeExample()
{
UID = "",
Health = 100,
Name = "TestPlayer1",
Level = 10,
LastPlayTime = DateTime.UtcNow,
Items = new() { "gun", "frog", "banana" }
};
public static ReadmeExample TestData2 = new ReadmeExample()
{
UID = "",
Health = 90,
Name = "TestPlayer2",
Level = 15,
LastPlayTime = DateTime.UtcNow,
Items = new() { "apple", "box" }
};
}
global using Microsoft.VisualStudio.TestTools.UnitTesting;
[TestClass]
public class TestInit
{
[AssemblyInitialize]
public static void ClassInitialize( TestContext context )
{
Sandbox.Application.InitUnitTest();
}
}
global using Microsoft.VisualStudio.TestTools.UnitTesting;
[TestClass]
public class TestInit
{
[AssemblyInitialize]
public static void ClassInitialize( TestContext context )
{
Sandbox.Application.InitUnitTest();
}
}
using Sandbox;
[TestClass]
public partial class LibraryTests
{
[TestMethod]
public void SceneTest()
{
var scene = new Scene();
using ( scene.Push() )
{
var go = new GameObject();
Assert.AreEqual( 1, scene.Directory.GameObjectCount );
}
}
}
using Sandbox;
[TestClass]
public partial class LibraryTests
{
[TestMethod]
public void SceneTest()
{
var scene = new Scene();
using ( scene.Push() )
{
var go = new GameObject();
Assert.AreEqual( 1, scene.Directory.GameObjectCount );
}
}
}
using System;
using Editor.MovieMaker;
namespace Sandbox.MovieMaker.Test;
[TestClass]
public sealed class EditingTests
{
private static PropertySignal<float> CreateCrossFadeWithRange( MovieTimeRange fadeRange )
{
var from = 1f.AsSignal();
var to = 2f.AsSignal();
return from.CrossFade( to, fadeRange );
}
[TestMethod]
public void SimpleCrossFade()
{
var fade = CreateCrossFadeWithRange( (0d, 1d) );
Assert.AreEqual( 1f, fade.GetValue( 0 ) );
Assert.AreEqual( 1.5f, fade.GetValue( 0.5 ) );
Assert.AreEqual( 2f, fade.GetValue( 1 ) );
}
[TestMethod]
public void CrossFadeWithInnerRange()
{
var fade = CreateCrossFadeWithRange( (0.25d, 0.75d) );
Assert.AreEqual( 1f, fade.GetValue( 0 ) );
Assert.AreEqual( 1f, fade.GetValue( 0.25 ) );
Assert.AreEqual( 1.5f, fade.GetValue( 0.5 ) );
Assert.AreEqual( 2f, fade.GetValue( 0.75 ) );
Assert.AreEqual( 2f, fade.GetValue( 1 ) );
}
[TestMethod]
public void OverlappingCrossFade()
{
var fade1 = CreateCrossFadeWithRange( (0d, 0.75d) );
var fade2 = CreateCrossFadeWithRange( (0.25d, 1d) );
var fade = fade1.CrossFade( fade2, (0d, 1d) );
Console.WriteLine( fade.ToString() );
Assert.AreEqual( 1f, fade.GetValue( 0d ) );
Assert.AreEqual( 2f, fade.GetValue( 1d ) );
}
[TestMethod]
public void ReduceHardCut()
{
var signal = 1f.AsSignal()
.HardCut( 2f, 2d )
.HardCut( 1f, 1d )
.Reduce();
Assert.AreEqual( 1f, signal );
}
[TestMethod]
public void ReduceHardCut2()
{
var signal1 = 1f.AsSignal()
.HardCut( 2f, 2d );
var signal2 = 2f.AsSignal()
.HardCut( 1f, 2d );
var reduced1 = signal1
.HardCut( signal2, 2d )
.Reduce();
Console.WriteLine( reduced1 );
Assert.AreEqual( 1f, reduced1 );
var reduced2 = signal2
.HardCut( signal1, 2d )
.Reduce();
Console.WriteLine( reduced2 );
Assert.AreEqual( 2f, reduced2 );
}
[TestMethod]
public void ReduceCrossFade()
{
var signal = 1f.AsSignal()
.CrossFade( 2f, (3d, 4d) )
.CrossFade( 1f, (1d, 2d) )
.Reduce();
Assert.AreEqual( 1f, signal );
}
[TestMethod]
public void ReduceCrossFadeHardCut()
{
var signal1 = 1f.AsSignal();
var signal2 = 1f.AsSignal()
.CrossFade( 2f, (2d, 3d) )
.CrossFade( 1f, (4d, 5d) );
var reduced = signal1.HardCut( signal2, 1d )
.Reduce();
Console.WriteLine( reduced );
Assert.AreEqual( signal2, reduced );
}
[TestMethod]
public void ReduceShift()
{
var signal = (1f.AsSignal() + 1d)
.Reduce();
Assert.AreEqual( 1f, signal );
}
[TestMethod]
public void HardCut()
{
var signal = 1f.AsSignal().HardCut( 2f, 1d );
Console.WriteLine( signal.ToString() );
Assert.AreEqual( 1f, signal.GetValue( 0d ) );
Assert.AreEqual( 1f, signal.GetValue( 1d - MovieTime.Epsilon ) );
Assert.AreEqual( 2f, signal.GetValue( 1d ) );
}
[TestMethod]
public void Blend()
{
var signal = 1f.AsSignal().Blend( 2f, 0.5f );
Console.WriteLine( signal.ToString() );
Assert.AreEqual( 1.5f, signal.GetValue( default ) );
}
[TestMethod]
public void SlidingStretch()
{
var slideTransform = new SlidingStretchTransform( MovieTimeScale.FromCents( -1200 ), new MovieTimeRange( 1d, 2d ) );
Assert.AreEqual( MovieTransform.Identity, slideTransform.GetTransformAt( 0d ) );
Assert.AreEqual( MovieTransform.Identity, slideTransform.GetTransformAt( 1d ) );
Assert.AreEqual( new MovieTransform( 1d / 3d, MovieTimeScale.FromCents( -1200 ) ), slideTransform.GetTransformAt( 2d ) );
Assert.AreEqual( new MovieTransform( 1d / 3d, MovieTimeScale.FromCents( -1200 ) ), slideTransform.GetTransformAt( 3d ) );
}
[TestMethod]
[DataRow( 0d, 0d )]
[DataRow( 1d, 0d )]
[DataRow( 0d, 1d )]
[DataRow( 1d, 1d )]
public void SlidingStretchFromEnvelope( double fadeIn, double fadeOut )
{
var sourceDuration = MovieTime.FromSeconds( 1d );
var envelope = new TimeSelection( (2d, 4d),
new TimeSelection.Fade( fadeIn, InterpolationMode.Linear ),
new TimeSelection.Fade( fadeOut, InterpolationMode.Linear ) );
var (slideIn, slideOut) = SlidingStretchTransform.FromEnvelope( sourceDuration, envelope );
var finalTransform = slideOut.GetTransformAt( 1000d ) * slideIn.GetTransformAt( 1000d );
Assert.AreEqual( MovieTimeScale.Identity, finalTransform.Scale );
Assert.AreEqual( envelope.TotalTimeRange.Duration - sourceDuration, finalTransform.Translation );
}
}
using Sandbox;
[TestClass]
public partial class LibraryTests
{
[TestMethod]
public void SceneTest()
{
var scene = new Scene();
using ( scene.Push() )
{
var go = new GameObject();
Assert.AreEqual( 1, scene.Directory.GameObjectCount );
}
}
}
global using Microsoft.VisualStudio.TestTools.UnitTesting;
[TestClass]
public class TestInit
{
[AssemblyInitialize]
public static void ClassInitialize( TestContext context )
{
Sandbox.Application.InitUnitTest();
}
}
global using Microsoft.VisualStudio.TestTools.UnitTesting;
[TestClass]
public class TestInit
{
[AssemblyInitialize]
public static void ClassInitialize( TestContext context )
{
Sandbox.Application.InitUnitTest();
}
}
global using Microsoft.VisualStudio.TestTools.UnitTesting;
[TestClass]
public class TestInit
{
[AssemblyInitialize]
public static void ClassInitialize( TestContext context )
{
Sandbox.Application.InitUnitTest();
}
}
using Sandbox.TailBox;
using System;
using System.IO;
using System.Linq;
[TestClass]
public sealed class TailBoxExtendedUtilityTests
{
[DataTestMethod]
[DataRow( "flex-auto", "flex-grow: 1;" )]
[DataRow( "flex-none", "flex-shrink: 0;" )]
[DataRow( "basis-[33px]", "flex-basis: 33px;" )]
[DataRow( "order-3", "order: 3;" )]
[DataRow( "-order-2", "order: -2;" )]
[DataRow( "h-full", "height: 100%;" )]
[DataRow( "min-w-0", "min-width: 0;" )]
[DataRow( "min-w-[220px]", "min-width: 220px;" )]
[DataRow( "min-h-[24px]", "min-height: 24px;" )]
[DataRow( "max-w-screen", "max-width: 100vw;" )]
[DataRow( "aspect-square", "aspect-ratio: 1;" )]
[DataRow( "aspect-[4/3]", "aspect-ratio: 4/3;" )]
public void GeneratesAdditionalLayoutAndSizingUtilities( string className, string declaration )
{
AssertUtility( className, declaration );
}
[DataTestMethod]
[DataRow( "border-x", "border-left: 1px solid rgba( 139, 154, 164, 0.32 );" )]
[DataRow( "border-y-accent", "border-bottom: 1px solid #d7b46a;" )]
[DataRow( "border-l-[3px]", "border-left: 3px solid rgba( 139, 154, 164, 0.32 );" )]
[DataRow( "border-[3px]", "border-width: 3px;" )]
[DataRow( "border-[#123456]/25", "border-color: rgba( 18, 52, 86, 0.25 );" )]
[DataRow( "rounded-br-md", "border-radius: 0px 0px 8px 0px;" )]
[DataRow( "rounded-s-lg", "border-radius: 12px 0px 0px 12px;" )]
[DataRow( "rounded-ee-[9px]", "border-radius: 0px 0px 9px 0px;" )]
public void GeneratesAdditionalBorderAndRadiusUtilities( string className, string declaration )
{
AssertUtility( className, declaration );
}
[DataTestMethod]
[DataRow( "text-right", "text-align: right;" )]
[DataRow( "lowercase", "text-transform: lowercase;" )]
[DataRow( "capitalize", "text-transform: capitalize;" )]
[DataRow( "text-[length:22px]/7", "line-height: 28px;" )]
[DataRow( "font-[Roboto_Slab]", "font-family: Roboto Slab;" )]
[DataRow( "-tracking-wide", "letter-spacing: -0.025em;" )]
[DataRow( "decoration-[3px]", "text-decoration-thickness: 3px;" )]
[DataRow( "underline-offset-4", "text-decoration-underline-offset: 4px;" )]
[DataRow( "-underline-offset-2", "text-decoration-underline-offset: -2px;" )]
[DataRow( "text-[color:#123456]/50", "color: rgba( 18, 52, 86, 0.5 );" )]
[DataRow( "text-accent/50", "color: rgba( 215, 180, 106, 0.5 );" )]
public void GeneratesAdditionalTypographyUtilities( string className, string declaration )
{
AssertUtility( className, declaration );
}
[DataTestMethod]
[DataRow( "bg-contain", "background-size: contain;" )]
[DataRow( "bg-center", "background-position: center;" )]
[DataRow( "bg-no-repeat", "background-repeat: no-repeat;" )]
[DataRow( "bg-[linear-gradient(red,_blue)]", "background-image: linear-gradient(red, blue);" )]
[DataRow( "bg-[image:url(/ui/panel.png)]", "background-image: url(/ui/panel.png);" )]
public void GeneratesAdditionalBackgroundSurfaceUtilities( string className, string declaration )
{
AssertUtility( className, declaration );
}
[DataTestMethod]
[DataRow( "opacity-75", "opacity: 0.75;" )]
[DataRow( "opacity-[0.35]", "opacity: 0.35;" )]
[DataRow( "shadow", "box-shadow: 0 12px 32px rgba( 0, 0, 0, 0.34 );" )]
[DataRow( "shadow-none", "box-shadow: none;" )]
[DataRow( "shadow-[0_0_12px_black]", "box-shadow: 0 0 12px black;" )]
[DataRow( "text-shadow", "text-shadow: 0 2px 4px rgba( 0, 0, 0, 0.4 );" )]
[DataRow( "text-shadow-[0_0_12px_black]", "text-shadow: 0 0 12px black;" )]
[DataRow( "blur", "filter-blur: 8px;" )]
[DataRow( "contrast-125", "filter-contrast: 1.25;" )]
[DataRow( "saturate-[1.25]", "filter-saturate: 1.25;" )]
[DataRow( "-hue-rotate-30", "filter-hue-rotate: -30deg;" )]
[DataRow( "invert", "filter-invert: 1;" )]
[DataRow( "grayscale-0", "filter-saturate: 0;" )]
[DataRow( "drop-shadow-sm", "filter-drop-shadow: 0 2px 8px rgba( 0, 0, 0, 0.24 );" )]
[DataRow( "backdrop-brightness-125", "backdrop-filter-brightness: 1.25;" )]
[DataRow( "backdrop-blur-sm", "backdrop-filter-blur: 4px;" )]
[DataRow( "mix-blend-multiply", "mix-blend-mode: multiply;" )]
public void GeneratesAdditionalEffectsUtilities( string className, string declaration )
{
AssertUtility( className, declaration );
}
[DataTestMethod]
[DataRow( "transition", "transition-property: all;" )]
[DataRow( "transition-all", "transition-property: all;" )]
[DataRow( "transition-colors", "transition-property: color, background-color, border-color, text-decoration-color;" )]
[DataRow( "transition-opacity", "transition-property: opacity;" )]
[DataRow( "transition-shadow", "transition-property: box-shadow, text-shadow, filter-drop-shadow;" )]
[DataRow( "transition-transform", "transition-property: transform;" )]
[DataRow( "duration-[275ms]", "transition-duration: 275ms;" )]
[DataRow( "delay-300", "transition-delay: 0.3s;" )]
[DataRow( "ease-[cubic-bezier(0.2,_0,_0,_1)]", "transition-timing-function: cubic-bezier(0.2, 0, 0, 1);" )]
[DataRow( "transform-none", "transform: none;" )]
[DataRow( "transform-[translateX(4px)_scale(1.04)]", "transform: translateX(4px) scale(1.04);" )]
[DataRow( "origin-bottom-right", "transform-origin: bottom right;" )]
[DataRow( "animate-none", "animation: none;" )]
[DataRow( "animate-[fade_1s_ease]", "animation: fade 1s ease;" )]
public void GeneratesMotionUtilities( string className, string declaration )
{
AssertUtility( className, declaration );
}
[DataTestMethod]
[DataRow( "fixed", TailBoxSkipReason.UnsupportedValue )]
[DataRow( "space-x-4", TailBoxSkipReason.UnsupportedSelectorVariant )]
[DataRow( "bg-gradient-to-r", TailBoxSkipReason.UnsupportedUtility )]
[DataRow( "bg-[paint-token]", TailBoxSkipReason.UnsupportedProperty )]
[DataRow( "border-dashed", TailBoxSkipReason.UnsupportedProperty )]
[DataRow( "decoration-wavy", TailBoxSkipReason.UnsupportedProperty )]
[DataRow( "text-lg/unknown", TailBoxSkipReason.UnsupportedModifier )]
[DataRow( "text-accent/not-real", TailBoxSkipReason.UnsupportedModifier )]
[DataRow( "animate-spin", TailBoxSkipReason.UnsupportedUtility )]
[DataRow( "translate-x-4", TailBoxSkipReason.UnsupportedUtility )]
[DataRow( "touch-pan-x", TailBoxSkipReason.UnsupportedProperty )]
public void ReportsAdditionalUnsupportedUtilitiesWithStableReasons( string className, TailBoxSkipReason reason )
{
var result = GenerateSafelist( className );
Assert.AreEqual( 0, result.GeneratedClassCount );
AssertSkip( result, className, reason );
Assert.IsTrue( result.Warnings.Single().StartsWith( className + ":", StringComparison.Ordinal ) );
}
[TestMethod]
public void ImportantArbitraryPropertyComposesInOneRule()
{
var result = GenerateSafelist( "![z-index:5]" );
StringAssert.Contains( result.GeneratedScss, RuleStart( "![z-index:5]" ) );
StringAssert.Contains( result.GeneratedScss, "z-index: 5 !important;" );
Assert.AreEqual( 1, result.GeneratedClassCount );
}
private static void AssertUtility( string className, string declaration )
{
var result = GenerateSafelist( className );
StringAssert.Contains( result.GeneratedScss, RuleStart( className ) );
StringAssert.Contains( result.GeneratedScss, declaration );
Assert.AreEqual( 1, result.GeneratedClassCount, $"Expected one generated rule for {className}." );
Assert.AreEqual( 0, result.SkippedClassCount, $"Expected no skipped classes for {className}." );
Assert.AreEqual( 0, result.Warnings.Count, $"Expected no warnings for {className}." );
}
private static void AssertSkip( TailBoxGenerationResult result, string className, TailBoxSkipReason reason )
{
var skipped = result.Skipped.SingleOrDefault( item => item.ClassName == className );
Assert.IsNotNull( skipped, $"Expected '{className}' to be skipped." );
Assert.AreEqual( reason, skipped.Reason, $"Unexpected skip reason for '{className}': {skipped.Detail}" );
Assert.IsFalse( string.IsNullOrWhiteSpace( skipped.Detail ) );
}
private static TailBoxGenerationResult GenerateSafelist( params string[] classes )
{
var root = CreateTempProject();
try
{
var config = TailBoxConfig.CreateDefault();
config.Safelist.AddRange( classes );
return TailBoxEditorProject.Generate( root, config, writeFile: false );
}
finally
{
DeleteTempProject( root );
}
}
private static string RuleStart( string className )
{
Assert.IsTrue( TailBoxCandidateParser.TryParse( className, out var candidate, out _ ), $"Expected '{className}' to parse." );
return "." + TailBoxUtilityCompiler.EscapeClassSelector( className )
+ string.Concat( candidate.Variants.Select( variant => variant.SelectorSuffix ) )
+ " {";
}
private static string CreateTempProject()
{
return TailBoxTestPaths.CreateTempProject();
}
private static void DeleteTempProject( string root )
{
if ( Directory.Exists( root ) )
{
Directory.Delete( root, true );
}
}
}
using Sandbox;
[TestClass]
public partial class LibraryTests
{
[TestMethod]
public void SceneTest()
{
var scene = new Scene();
using ( scene.Push() )
{
var go = new GameObject();
Assert.AreEqual( 1, scene.Directory.GameObjectCount );
}
}
}
global using Microsoft.VisualStudio.TestTools.UnitTesting;
[TestClass]
public class TestInit
{
[AssemblyInitialize]
public static void ClassInitialize( TestContext context )
{
Sandbox.Application.InitUnitTest();
}
}
global using Microsoft.VisualStudio.TestTools.UnitTesting;
[TestClass]
public class TestInit
{
public static Sandbox.TestAppSystem AppSystem;
[AssemblyInitialize]
public static void AssemblyInitialize( TestContext context )
{
AppSystem = new Sandbox.TestAppSystem();
AppSystem.Init();
}
[AssemblyCleanup]
public static void AssemblyCleanup()
{
AppSystem.Shutdown();
}
}
using Sandbox;
[TestClass]
public partial class LibraryTests
{
[TestMethod]
public void SceneTest()
{
var scene = new Scene();
using ( scene.Push() )
{
var go = new GameObject();
Assert.AreEqual( 1, scene.Directory.GameObjectCount );
}
}
}
global using Microsoft.VisualStudio.TestTools.UnitTesting;
[TestClass]
public class TestInit
{
[AssemblyInitialize]
public static void ClassInitialize( TestContext context )
{
Sandbox.Application.InitUnitTest();
}
}
using Sandbox;
[TestClass]
public partial class LibraryTests
{
[TestMethod]
public void SceneTest()
{
var scene = new Scene();
using ( scene.Push() )
{
var go = new GameObject();
Assert.AreEqual( 1, scene.Directory.GameObjectCount );
}
}
}
using Sandbox;
[TestClass]
public partial class LibraryTests
{
[TestMethod]
public void SceneTest()
{
var scene = new Scene();
using ( scene.Push() )
{
var go = new GameObject();
Assert.AreEqual( 1, scene.Directory.GameObjectCount );
}
}
}
using Sandbox;
[TestClass]
public partial class LibraryTests
{
[TestMethod]
public void SceneTest()
{
var scene = new Scene();
using ( scene.Push() )
{
var go = new GameObject();
Assert.AreEqual( 1, scene.Directory.GameObjectCount );
}
}
}
global using Microsoft.VisualStudio.TestTools.UnitTesting;
[TestClass]
public class TestInit
{
[AssemblyInitialize]
public static void ClassInitialize( TestContext context )
{
Sandbox.Application.InitUnitTest();
}
}
using Sandbox;
[TestClass]
public partial class LibraryTests
{
[TestMethod]
public void SceneTest()
{
var scene = new Scene();
using ( scene.Push() )
{
var go = new GameObject();
Assert.AreEqual( 1, scene.Directory.GameObjectCount );
}
}
}
global using Microsoft.VisualStudio.TestTools.UnitTesting;
[TestClass]
public class TestInit
{
[AssemblyInitialize]
public static void ClassInitialize( TestContext context )
{
Sandbox.Application.InitUnitTest();
}
}
global using Microsoft.VisualStudio.TestTools.UnitTesting;
[TestClass]
public class TestInit
{
[AssemblyInitialize]
public static void ClassInitialize(TestContext context)
{
Sandbox.Application.InitUnitTest();
}
}
global using Microsoft.VisualStudio.TestTools.UnitTesting;
[TestClass]
public class TestInit
{
[AssemblyInitialize]
public static void ClassInitialize( TestContext context )
{
Sandbox.Application.InitUnitTest();
}
}
global using Microsoft.VisualStudio.TestTools.UnitTesting;
[TestClass]
public class TestInit
{
[AssemblyInitialize]
public static void ClassInitialize( TestContext context )
{
Sandbox.Application.InitUnitTest();
}
}
using Sandbox;
[TestClass]
public partial class LibraryTests
{
[TestMethod]
public void SceneTest()
{
var scene = new Scene();
using ( scene.Push() )
{
var go = new GameObject();
Assert.AreEqual( 1, scene.Directory.GameObjectCount );
}
}
}
using Sandbox;
[TestClass]
public partial class LibraryTests
{
[TestMethod]
public void SceneTest()
{
var scene = new Scene();
using ( scene.Push() )
{
var go = new GameObject();
Assert.AreEqual( 1, scene.Directory.GameObjectCount );
}
}
}
using Sandbox;
[TestClass]
public partial class LibraryTests
{
[TestMethod]
public void SceneTest()
{
var scene = new Scene();
using ( scene.Push() )
{
var go = new GameObject();
Assert.AreEqual( 1, scene.Directory.GameObjectCount );
}
}
}
global using Microsoft.VisualStudio.TestTools.UnitTesting;
namespace WackyLib.Tests;
[TestClass]
public class TestInit
{
[AssemblyInitialize]
public static void ClassInitialize( TestContext context )
{
Sandbox.Application.InitUnitTest<TestInit>( false );
}
[AssemblyCleanup]
public static void AssemblyCleanup()
{
Sandbox.Application.ShutdownUnitTest();
}
}
using Sandbox;
[TestClass]
public partial class LibraryTests
{
[TestMethod]
public void SceneTest()
{
var scene = new Scene();
using ( scene.Push() )
{
var go = new GameObject();
Assert.AreEqual( 1, scene.Directory.GameObjectCount );
}
}
}
using Sandbox;
[TestClass]
public partial class LibraryTests
{
[TestMethod]
public void SceneTest()
{
var scene = new Scene();
using ( scene.Push() )
{
var go = new GameObject();
Assert.AreEqual( 1, scene.Directory.GameObjectCount );
}
}
}
using Sandbox;
[TestClass]
public partial class LibraryTests
{
[TestMethod]
public void SceneTest()
{
var scene = new Scene();
using ( scene.Push() )
{
var go = new GameObject();
Assert.AreEqual( 1, scene.Directory.GameObjectCount );
}
}
}
global using Microsoft.VisualStudio.TestTools.UnitTesting;
[TestClass]
public class TestInit
{
public static Sandbox.TestAppSystem AppSystem;
[AssemblyInitialize]
public static void AssemblyInitialize()
{
AppSystem = new Sandbox.TestAppSystem();
AppSystem.Init();
}
[AssemblyCleanup]
public static void AssemblyCleanup()
{
AppSystem.Shutdown();
}
}
global using Microsoft.VisualStudio.TestTools.UnitTesting;
[TestClass]
public class TestInit
{
[AssemblyInitialize]
public static void ClassInitialize( TestContext context )
{
Sandbox.Application.InitUnitTest();
}
}
using Sandbox.TailBox;
using System;
using System.IO;
using System.Linq;
[TestClass]
public sealed class TailBoxDemoTests
{
[TestMethod]
public void DemoMenuGeneratesBroadUtilitySetWithoutStructuredSkips()
{
var repoRoot = FindRepositoryRoot();
if ( repoRoot is null )
Assert.Inconclusive( "Repository root could not be located for the TailBox demo fixture." );
var demoPath = Path.Combine( repoRoot, "Code", "Demo", "TailBoxDemoMenu.razor" );
var result = new TailBoxGenerator().GenerateFromSources(
new[] { new TailBoxSourceText( demoPath, File.ReadAllText( demoPath ) ) },
TailBoxConfig.CreateDefault(),
repoRoot,
"Code/tailwand.generated.scss" );
Assert.IsTrue( result.GeneratedClassCount > 130, "Expected the demo to exercise a broad utility set." );
Assert.AreEqual( 0, result.SkippedClassCount, string.Join( Environment.NewLine, result.Skipped.Select( item => $"{item.ClassName}: {item.Detail}" ) ) );
StringAssert.Contains( result.GeneratedScss, RuleStart( "blur-sm" ) );
StringAssert.Contains( result.GeneratedScss, "filter-blur: 4px;" );
}
private static string RuleSelector( string className )
{
return "." + TailBoxUtilityCompiler.EscapeClassSelector( className );
}
private static string RuleStart( string className )
{
Assert.IsTrue( TailBoxCandidateParser.TryParse( className, out var candidate, out _ ), $"Expected '{className}' to parse." );
return RuleSelector( className )
+ string.Concat( candidate.Variants.Select( variant => variant.SelectorSuffix ) )
+ " {";
}
private static string FindRepositoryRoot()
{
foreach ( var start in new[] { Directory.GetCurrentDirectory(), AppContext.BaseDirectory } )
{
var current = new DirectoryInfo( start );
while ( current is not null )
{
var fixture = Path.Combine( current.FullName, "Code", "Demo", "TailBoxDemoMenu.razor" );
if ( File.Exists( fixture ) )
return current.FullName;
current = current.Parent;
}
}
return null;
}
}
using Sandbox.TailBox;
using System;
using System.IO;
using System.Linq;
[TestClass]
public sealed class TailBoxGeneratorTests
{
[TestMethod]
public void ExtractsStaticDynamicAndSafelistedClasses()
{
var text = """
<div class="flex p-4 @(IsActive ? "hover:bg-accent" : "text-accent")"></div>
<Button class='w-1/2 px-[14px]' />
@* tailbox safelist: intro:opacity-0 bg-[#0d1418] *@
""";
var classes = TailBoxClassExtractor.ExtractClassesFromText( text );
Assert.IsTrue( classes.Contains( "flex" ) );
Assert.IsTrue( classes.Contains( "p-4" ) );
Assert.IsTrue( classes.Contains( "hover:bg-accent" ) );
Assert.IsTrue( classes.Contains( "text-accent" ) );
Assert.IsTrue( classes.Contains( "w-1/2" ) );
Assert.IsTrue( classes.Contains( "px-[14px]" ) );
Assert.IsTrue( classes.Contains( "intro:opacity-0" ) );
Assert.IsTrue( classes.Contains( "bg-[#0d1418]" ) );
}
[TestMethod]
public void SavesAndLoadsConfigWithDefaultsMerged()
{
var root = CreateTempProject();
try
{
var config = TailBoxEditorProject.SaveDefaultConfig( root );
config.Colors["brand"] = "#123456";
config.Safelist.Add( "text-brand" );
TailBoxEditorProject.SaveConfig( root, config );
var loaded = TailBoxEditorProject.LoadConfig( root );
Assert.AreEqual( "Code/tailwand.generated.scss", loaded.OutputPath );
Assert.AreEqual( "#d7b46a", loaded.Colors["accent"] );
Assert.AreEqual( "#123456", loaded.Colors["brand"] );
Assert.IsFalse( loaded.Screens.ContainsKey( "md" ) );
Assert.AreEqual( "0.15s", loaded.Durations["150"] );
Assert.AreEqual( "1", loaded.Opacity["100"] );
Assert.IsTrue( loaded.Safelist.Contains( "text-brand" ) );
}
finally
{
DeleteTempProject( root );
}
}
[TestMethod]
public void GeneratesRepresentativeUtilities()
{
var root = CreateTempProject();
try
{
File.WriteAllText( Path.Combine( root, "Code", "Screen.razor" ), """
<div class="flex w-full w-1/2 p-4 px-[14px] bg-[#0d1418] text-accent z-10"></div>
""" );
var result = TailBoxEditorProject.Generate( root, TailBoxConfig.CreateDefault() );
var scss = result.GeneratedScss;
StringAssert.Contains( scss, ".flex {" );
StringAssert.Contains( scss, "display: flex;" );
StringAssert.Contains( scss, RuleStart( "w-1/2" ) );
StringAssert.Contains( scss, "width: 50%;" );
StringAssert.Contains( scss, ".p-4 {" );
StringAssert.Contains( scss, "padding: 16px;" );
StringAssert.Contains( scss, RuleStart( "px-[14px]" ) );
StringAssert.Contains( scss, "padding-left: 14px;" );
StringAssert.Contains( scss, "padding-right: 14px;" );
StringAssert.Contains( scss, RuleStart( "bg-[#0d1418]" ) );
StringAssert.Contains( scss, "background-color: #0d1418;" );
StringAssert.Contains( scss, ".text-accent {" );
StringAssert.Contains( scss, "color: #d7b46a;" );
StringAssert.Contains( scss, RuleStart( "z-10" ) );
StringAssert.Contains( scss, "z-index: 10;" );
Assert.AreEqual( 8, result.GeneratedClassCount );
Assert.IsTrue( File.Exists( Path.Combine( root, "Code", "tailwand.generated.scss" ) ) );
}
finally
{
DeleteTempProject( root );
}
}
[TestMethod]
public void EscapesSpecialSelectorCharacters()
{
var root = CreateTempProject();
try
{
var config = TailBoxConfig.CreateDefault();
config.Safelist.AddRange( new[]
{
"w-1/2",
"bg-[#0d1418]",
"z-[100%]",
"rounded-[10px]",
"-mt-2"
} );
var result = TailBoxEditorProject.Generate( root, config, writeFile: false );
var scss = result.GeneratedScss;
StringAssert.Contains( scss, RuleSelector( "w-1/2" ) );
StringAssert.Contains( scss, RuleSelector( "bg-[#0d1418]" ) );
StringAssert.Contains( scss, RuleSelector( "z-[100%]" ) );
StringAssert.Contains( scss, RuleSelector( "rounded-[10px]" ) );
StringAssert.Contains( scss, RuleSelector( "-mt-2" ) );
StringAssert.Contains( scss, "margin-top: -8px;" );
}
finally
{
DeleteTempProject( root );
}
}
[TestMethod]
public void SkippedItemsCarryStableReasonsAndSourcePaths()
{
var root = CreateTempProject();
try
{
var razor = Path.Combine( root, "Code", "Screen.razor" );
File.WriteAllText( razor, """
<div class="grid unknown:flex hover:flex first:flex rotate-45 [--brand:#fff]"></div>
""" );
var result = TailBoxEditorProject.Generate( root, TailBoxConfig.CreateDefault(), writeFile: false );
Assert.AreEqual( 0, result.GeneratedClassCount );
AssertSkip( result, "grid", TailBoxSkipReason.UnsupportedValue, razor );
AssertSkip( result, "unknown:flex", TailBoxSkipReason.UnsupportedVariant, razor );
AssertSkip( result, "hover:flex", TailBoxSkipReason.UnsupportedSelectorVariant, razor );
AssertSkip( result, "first:flex", TailBoxSkipReason.UnsupportedSelectorVariant, razor );
AssertSkip( result, "rotate-45", TailBoxSkipReason.UnsupportedUtility, razor );
AssertSkip( result, "[--brand:#fff]", TailBoxSkipReason.UnsupportedArbitraryProperty, razor );
Assert.AreEqual( result.SkippedClassCount, result.SkippedClasses.Count );
}
finally
{
DeleteTempProject( root );
}
}
[TestMethod]
public void GeneratesConstructionDashboardExampleDeterministically()
{
var repoRoot = FindRepositoryRoot();
if ( repoRoot is null )
Assert.Inconclusive( "Repository root could not be located for the ConstructionDashboard fixture." );
var root = CreateTempProject();
try
{
var exampleRazor = Path.Combine( repoRoot, "Examples", "ConstructionDashboard", "Code", "ConstructionDashboard.razor.example" );
var exampleConfig = Path.Combine( repoRoot, "Examples", "ConstructionDashboard", TailBoxConfig.FileName );
Directory.CreateDirectory( Path.Combine( root, "Code" ) );
File.Copy( exampleRazor, Path.Combine( root, "Code", "ConstructionDashboard.razor" ), overwrite: true );
var config = TailBoxConfig.LoadJson( File.ReadAllText( exampleConfig ), exampleConfig );
var first = TailBoxEditorProject.Generate( root, config, writeFile: false );
var second = TailBoxEditorProject.Generate( root, config, writeFile: false );
Assert.IsTrue( first.GeneratedClassCount > 35, "Expected the example to generate a broad utility set." );
Assert.AreEqual( 0, first.SkippedClassCount );
Assert.AreEqual( first.GeneratedScss, second.GeneratedScss );
CollectionAssert.AreEqual( first.GeneratedClasses.ToArray(), second.GeneratedClasses.ToArray() );
StringAssert.Contains( first.GeneratedScss, RuleStart( "w-1/4" ) );
StringAssert.Contains( first.GeneratedScss, "color: #d7b46a;" );
}
finally
{
DeleteTempProject( root );
}
}
[TestMethod]
public void SboxStyleParserAcceptsGeneratedEscapedSelectorsWhenAvailable()
{
try
{
var panelType = Type.GetType( "Sandbox.UI.Panel, Sandbox.Engine", throwOnError: true );
var panel = Activator.CreateInstance( panelType );
var styleSheet = panelType.GetProperty( "StyleSheet" )?.GetValue( panel );
var parse = styleSheet?.GetType().GetMethod( "Parse", new[] { typeof( string ), typeof( bool ) } );
parse?.Invoke(
styleSheet,
new object[]
{
RuleStart( "bg-accent" ) + " background-color: #d7b46a; }\n" + RuleStart( "w-1/2" ) + " width: 50%; }",
false
} );
}
catch ( Exception ex ) when ( ex is NullReferenceException or InvalidOperationException or FileNotFoundException or System.Reflection.TargetInvocationException )
{
Assert.Inconclusive( "s&box style parsing is not available in this headless test context: " + ex.Message );
}
}
[TestMethod]
public void WatcherPathFilterIgnoresGeneratedOutputAndRequiresConfigForOptIn()
{
var root = CreateTempProject();
try
{
var output = Path.Combine( root, "Code", "tailwand.generated.scss" );
var razor = Path.Combine( root, "Code", "Screen.razor" );
File.WriteAllText( razor, "<div class=\"flex\"></div>" );
Assert.IsFalse( TailBoxEditorWatcher.IsProjectOptedIn( root ) );
Assert.IsFalse( TailBoxEditorWatcher.ShouldHandleChangedPath( root, output, output ) );
Assert.IsTrue( TailBoxEditorWatcher.ShouldHandleChangedPath( root, output, razor ) );
TailBoxEditorProject.SaveDefaultConfig( root );
Assert.IsTrue( TailBoxEditorWatcher.IsProjectOptedIn( root ) );
}
finally
{
DeleteTempProject( root );
}
}
private static string CreateTempProject()
{
return TailBoxTestPaths.CreateTempProject();
}
private static void DeleteTempProject( string root )
{
if ( Directory.Exists( root ) )
{
Directory.Delete( root, true );
}
}
private static void AssertSkip( TailBoxGenerationResult result, string className, TailBoxSkipReason reason, string sourcePath )
{
var skipped = result.Skipped.SingleOrDefault( item => item.ClassName == className );
Assert.IsNotNull( skipped, $"Expected '{className}' to be skipped." );
Assert.AreEqual( reason, skipped.Reason );
Assert.AreEqual( Path.GetFullPath( sourcePath ), Path.GetFullPath( skipped.SourcePath ) );
Assert.IsFalse( string.IsNullOrWhiteSpace( skipped.Detail ) );
}
private static string RuleSelector( string className )
{
return "." + TailBoxUtilityCompiler.EscapeClassSelector( className );
}
private static string RuleStart( string className )
{
Assert.IsTrue( TailBoxCandidateParser.TryParse( className, out var candidate, out _ ), $"Expected '{className}' to parse." );
return RuleSelector( className )
+ string.Concat( candidate.Variants.Select( variant => variant.SelectorSuffix ) )
+ " {";
}
private static string FindRepositoryRoot()
{
foreach ( var start in new[] { Directory.GetCurrentDirectory(), AppContext.BaseDirectory } )
{
var current = new DirectoryInfo( start );
while ( current is not null )
{
var fixture = Path.Combine( current.FullName, "Examples", "ConstructionDashboard", "Code", "ConstructionDashboard.razor.example" );
if ( File.Exists( fixture ) )
return current.FullName;
current = current.Parent;
}
}
return null;
}
}
using Sandbox;
[TestClass]
public class SyncToolYamlRendererTests
{
[TestMethod]
public void EmptyInputProducesEmptyOutput()
{
Assert.AreEqual( "", SyncToolYamlRenderer.RenderFromJson( null ) );
Assert.AreEqual( "", SyncToolYamlRenderer.RenderFromJson( "" ) );
}
[TestMethod]
public void EmptyObjectAndArrayRenderAsFlowStyle()
{
Assert.AreEqual( "{}\n", SyncToolYamlRenderer.RenderFromJson( "{}" ) );
Assert.AreEqual( "[]\n", SyncToolYamlRenderer.RenderFromJson( "[]" ) );
}
[TestMethod]
public void InvalidJsonReturnsInputUnchanged()
{
var notJson = "not: real: json: ::";
Assert.AreEqual( notJson, SyncToolYamlRenderer.RenderFromJson( notJson ) );
}
[TestMethod]
public void TopLevelKeysAreSortedAlphabetically()
{
var json = "{\"zeta\":1,\"alpha\":2,\"mu\":3}";
var yaml = SyncToolYamlRenderer.RenderFromJson( json );
Assert.AreEqual( "alpha: 2\nmu: 3\nzeta: 1\n", yaml );
}
[TestMethod]
public void NestedObjectsAreSortedRecursively()
{
var json = "{\"outer\":{\"zeta\":1,\"alpha\":2}}";
var yaml = SyncToolYamlRenderer.RenderFromJson( json );
Assert.AreEqual( "outer:\n alpha: 2\n zeta: 1\n", yaml );
}
[TestMethod]
public void DifferentKeyOrdersProduceIdenticalOutput()
{
var a = "{\"slug\":\"hello\",\"method\":\"POST\",\"enabled\":true}";
var b = "{\"enabled\":true,\"method\":\"POST\",\"slug\":\"hello\"}";
Assert.AreEqual(
SyncToolYamlRenderer.RenderFromJson( a ),
SyncToolYamlRenderer.RenderFromJson( b )
);
}
[TestMethod]
public void OutputUsesYamlSyntaxNotJsonSyntax()
{
var json = "{\"name\":\"hooked\",\"enabled\":true,\"max\":42}";
var yaml = SyncToolYamlRenderer.RenderFromJson( json );
// Smoke check: the rendered text must look like YAML, not JSON.
// This is the regression we're guarding: prior to the fix the diff
// view rendered structured data as JSON.
StringAssert.DoesNotMatch( yaml, new System.Text.RegularExpressions.Regex( @"^\s*\{" ) );
StringAssert.Contains( yaml, "enabled: true" );
StringAssert.Contains( yaml, "max: 42" );
StringAssert.Contains( yaml, "name: \"hooked\"" );
}
[TestMethod]
public void StringValuesAreQuotedAndEscapedSafely()
{
var json = "{\"text\":\"a:b\\nc\"}";
var yaml = SyncToolYamlRenderer.RenderFromJson( json );
// Strings go through JSON quoting which is also valid YAML.
// The colon/newline must not leak as YAML structure.
Assert.AreEqual( "text: \"a:b\\nc\"\n", yaml );
}
[TestMethod]
public void BooleanAndNullAreUnquoted()
{
var json = "{\"a\":true,\"b\":false,\"c\":null}";
var yaml = SyncToolYamlRenderer.RenderFromJson( json );
Assert.AreEqual( "a: true\nb: false\nc: null\n", yaml );
}
[TestMethod]
public void IntegerAndDoubleAreUnquoted()
{
var json = "{\"i\":7,\"d\":1.5}";
var yaml = SyncToolYamlRenderer.RenderFromJson( json );
Assert.AreEqual( "d: 1.5\ni: 7\n", yaml );
}
[TestMethod]
public void ArraysOfObjectsRenderAsBlockSequence()
{
var json = "{\"steps\":[{\"name\":\"first\",\"id\":1},{\"name\":\"second\",\"id\":2}]}";
var yaml = SyncToolYamlRenderer.RenderFromJson( json );
var expected =
"steps:\n" +
" -\n" +
" id: 1\n" +
" name: \"first\"\n" +
" -\n" +
" id: 2\n" +
" name: \"second\"\n";
Assert.AreEqual( expected, yaml );
}
[TestMethod]
public void ArraysOfScalarsRenderAsBlockSequence()
{
var json = "{\"tags\":[\"a\",\"b\",\"c\"]}";
var yaml = SyncToolYamlRenderer.RenderFromJson( json );
Assert.AreEqual( "tags:\n - \"a\"\n - \"b\"\n - \"c\"\n", yaml );
}
[TestMethod]
public void TopLevelArrayRenders()
{
var json = "[1,2,3]";
var yaml = SyncToolYamlRenderer.RenderFromJson( json );
Assert.AreEqual( "- 1\n- 2\n- 3\n", yaml );
}
[TestMethod]
public void KeysWithNonIdentifierCharactersAreQuoted()
{
var json = "{\"weird key\":1,\"x:y\":2}";
var yaml = SyncToolYamlRenderer.RenderFromJson( json );
// Bare YAML keys must not contain spaces or colons, so the renderer
// quotes them. Sort order is by raw key (Ordinal).
StringAssert.Contains( yaml, "\"weird key\": 1" );
StringAssert.Contains( yaml, "\"x:y\": 2" );
}
[TestMethod]
public void EmptyNestedObjectAndArrayUseFlowStyle()
{
var json = "{\"obj\":{},\"arr\":[]}";
var yaml = SyncToolYamlRenderer.RenderFromJson( json );
Assert.AreEqual( "arr: []\nobj: {}\n", yaml );
}
}
using Sandbox;
public partial class LibraryTests
{
[TestMethod]
public void SceneTest()
{
var scene = new Scene();
using ( scene.Push() )
{
var go = new GameObject();
Assert.AreEqual( 1, scene.Directory.GameObjectCount );
}
}
}
global using Microsoft.VisualStudio.TestTools.UnitTesting;
[TestClass]
public class TestInit
{
[AssemblyInitialize]
public static void ClassInitialize( TestContext context )
{
Sandbox.Application.InitUnitTest();
}
}
global using Microsoft.VisualStudio.TestTools.UnitTesting;
[TestClass]
public class TestInit
{
[AssemblyInitialize]
public static void ClassInitialize( TestContext context )
{
Sandbox.Application.InitUnitTest();
}
}
using System.Linq;
namespace SandbankDatabase;
[TestClass]
public partial class MockFileIOProviderTest
{
[TestMethod]
public void CreateDirectory()
{
var provider = new MockFileIOProvider();
provider.CreateDirectory( "test/test2" );
Assert.IsTrue( provider.DirectoryExists( "test/test2" ) );
}
[TestMethod]
public void DeleteDirectory()
{
var provider = new MockFileIOProvider();
Assert.IsTrue( provider.DirectoryExists( "" ) );
Assert.IsTrue( provider.DirectoryExists( "/" ) );
Assert.IsFalse( provider.DirectoryExists( "test/test2" ) );
provider.CreateDirectory( "test/test2" );
Assert.IsTrue( provider.DirectoryExists( "test/test2" ) );
provider.DeleteDirectory( "test/test2" );
Assert.IsFalse( provider.DirectoryExists( "test/test2" ) );
provider.CreateDirectory( "test/test2" );
Assert.IsTrue( provider.DirectoryExists( "test/test2" ) );
provider.DeleteDirectory( "test" );
Assert.IsFalse( provider.DirectoryExists( "test/test2" ) );
Assert.IsFalse( provider.DirectoryExists( "test" ) );
}
[TestMethod]
public void WriteAllText()
{
var provider = new MockFileIOProvider();
provider.WriteAllText( "hello/there/test.txt", "This is a test file" );
Assert.AreEqual( "This is a test file", provider.ReadAllText( "hello/there/test.txt" ) );
}
[TestMethod]
public void ReadAllText()
{
var provider = new MockFileIOProvider();
Assert.AreEqual( null, provider.ReadAllText( "hello/testing/test.txt" ) );
}
[TestMethod]
public void FindFile()
{
var provider = new MockFileIOProvider();
provider.WriteAllText( "/folder/testing/a.txt", "A" );
provider.WriteAllText( "/folder/testing/b.txt", "B" );
provider.WriteAllText( "/folder/testing/c.txt", "C" );
var files = provider.FindFile( "folder/testing" ).ToList();
Assert.IsTrue( files.Count == 3 );
Assert.IsTrue( files.Contains( "a.txt" ) );
Assert.IsTrue( files.Contains( "b.txt" ) );
Assert.IsTrue( files.Contains( "c.txt" ) );
}
[TestMethod]
public void DeleteFile()
{
var provider = new MockFileIOProvider();
provider.WriteAllText( "/folder/testing/a.txt", "A" );
provider.WriteAllText( "/folder/testing/b.txt", "B" );
provider.WriteAllText( "/folder/testing/c.txt", "C" );
var files = provider.FindFile( "folder/testing" ).ToList();
Assert.IsTrue( files.Count == 3 );
provider.DeleteFile( "folder/testing/b" );
files = provider.FindFile( "folder/testing" ).ToList();
Assert.IsTrue( files.Count == 3 );
provider.DeleteFile( "folder/testing/b.txt" );
files = provider.FindFile( "folder/testing" ).ToList();
Assert.IsTrue( files.Count == 2 );
Assert.IsTrue( files.Contains( "a.txt" ) );
Assert.IsFalse( files.Contains( "b.txt" ) );
Assert.IsTrue( files.Contains( "c.txt" ) );
}
[TestMethod]
public void FindDirectory()
{
var provider = new MockFileIOProvider();
provider.CreateDirectory( "test/testdira" );
provider.CreateDirectory( "test/testdirb" );
provider.CreateDirectory( "test/testdirc" );
var directories = provider.FindDirectory( "/test/" ).ToList();
Assert.IsTrue( directories.Count == 3 );
Assert.IsTrue( directories.Contains( "testdira" ) );
Assert.IsTrue( directories.Contains( "testdirb" ) );
Assert.IsTrue( directories.Contains( "testdirc" ) );
directories = provider.FindDirectory( "" ).ToList();
Assert.IsTrue( directories.Count == 1 );
Assert.IsTrue( directories.Contains( "test" ) );
}
}
using Sandbox;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using static TestClasses;
namespace SandbankDatabase;
[TestClass]
public partial class SandbankTest
{
[TestInitialize]
public void Initialise()
{
InitialisationController.Initialise();
}
[TestCleanup]
public void Cleanup()
{
ConfigController.OBFUSCATE_FILES = false;
Sandbank.DeleteAllData();
Sandbank.Shutdown().GetAwaiter().GetResult();
}
[TestMethod]
public void TextObfuscationWorks()
{
var text = Obfuscation.ObfuscateFileText( "Wow! I love bacon! 豚肉が美味しい!" );
text = Obfuscation.UnobfuscateFileText( text );
Assert.AreEqual( "Wow! I love bacon! 豚肉が美味しい!", text );
}
[TestMethod]
public void TextObfuscationWorks_WithRealisticExample()
{
var original = @"{
""UID"": ""76561197997412036"",
""Health"": 100,
""BankBalance"": 0,
""Cash"": 10000,
""LastOnline"": ""2024-09-08T02:40:07.3391207\u002B01:00"",
""PlayerName"": ""anthonysharpy"",
""JumpCount"": 0,
""LivingThingsKilledCount"": 0,
""Achievements"": [],
""Hunger"": 100,
""EnduranceSkillLevel"": 0,
""EnduranceSkillLastDeterioratedTime"": 0,
""CompletedQuests"": [],
""StoredItems"": [
{
""Rarity"": 1,
""BackgroundColour"": ""0.9071,0.79477,0.33716,0.3"",
""UniqueID"": ""a70f35fa-cbdf-420e-9523-efce79e9c4c1"",
""XPos"": -1,
""YPos"": -1,
""Durability"": 100,
""Price"": 0,
""ItemName"": ""Fists"",
""PickupDisabled"": false,
""AmmoInClip"": 0
},
{
""Rarity"": 1,
""BackgroundColour"": ""0.61983,0.48797,0.19491,0.3"",
""UniqueID"": ""51becde0-ab0d-4103-b0d0-689eecfc5e00"",
""XPos"": -1,
""YPos"": -1,
""Durability"": 100,
""Price"": 0,
""ItemName"": ""Item Placer"",
""PickupDisabled"": false,
""AmmoInClip"": 0
},
{
""Rarity"": 3,
""BackgroundColour"": ""0.15048,0.9476,0.72171,0.3"",
""UniqueID"": ""8a73055a-ae58-4759-9172-afeb5d73de61"",
""XPos"": 0,
""YPos"": 0,
""Durability"": 100,
""Price"": 0,
""ItemName"": ""Grenade"",
""PickupDisabled"": false,
""AmmoInClip"": 0
},
{
""Rarity"": 3,
""BackgroundColour"": ""0.78122,0.13411,0.26792,0.3"",
""UniqueID"": ""f859ae80-e14b-43f9-af88-3887635efc63"",
""XPos"": 1,
""YPos"": 0,
""Durability"": 100,
""Price"": 0,
""ItemName"": ""Grenade"",
""PickupDisabled"": false,
""AmmoInClip"": 0
},
{
""Rarity"": 3,
""BackgroundColour"": ""0.30573,0.77256,0.48727,0.3"",
""UniqueID"": ""cbe5b32d-7afb-4b09-98c5-0b1eec6688bb"",
""XPos"": 2,
""YPos"": 0,
""Durability"": 100,
""Price"": 0,
""ItemName"": ""MP5"",
""PickupDisabled"": false,
""AmmoInClip"": 0
},
{
""Rarity"": 3,
""BackgroundColour"": ""0.57136,0.81519,0.96548,0.3"",
""UniqueID"": ""dbe6f248-7eae-4e58-9ce4-800b6e73721b"",
""XPos"": 6,
""YPos"": 0,
""Durability"": 100,
""Price"": 0,
""ItemName"": ""Grenade"",
""PickupDisabled"": false,
""AmmoInClip"": 0
},
{
""Rarity"": 3,
""BackgroundColour"": ""0.17717,0.17827,0.75903,0.3"",
""UniqueID"": ""e6aa5962-c1bf-4326-b22e-1edee07f2d98"",
""XPos"": 0,
""YPos"": 1,
""Durability"": 100,
""Price"": 0,
""ItemName"": ""Grenade"",
""PickupDisabled"": false,
""AmmoInClip"": 0
},
{
""Rarity"": 3,
""BackgroundColour"": ""0.97016,0.52173,0.33395,0.3"",
""UniqueID"": ""2531c680-e2c5-49ad-aa88-b86446e518ea"",
""XPos"": 1,
""YPos"": 1,
""Durability"": 100,
""Price"": 0,
""ItemName"": ""Ammo"",
""PickupDisabled"": false,
""AmmoInClip"": 0
},
{
""Rarity"": 3,
""BackgroundColour"": ""0.87892,0.43858,0.34768,0.3"",
""UniqueID"": ""b2a04888-e0da-4d16-a877-89ca0e201e4d"",
""XPos"": 6,
""YPos"": 1,
""Durability"": 100,
""Price"": 0,
""ItemName"": ""Ammo"",
""PickupDisabled"": false,
""AmmoInClip"": 0
},
{
""Rarity"": 3,
""BackgroundColour"": ""0.04801,0.02349,0.17021,0.3"",
""UniqueID"": ""4f484a7c-d7b7-4df7-9557-cbce6188d3f9"",
""XPos"": 0,
""YPos"": 2,
""Durability"": 100,
""Price"": 0,
""ItemName"": ""Grenade"",
""PickupDisabled"": false,
""AmmoInClip"": 0
}
],
""EquippedItemID"": ""30cf9992-1c8e-4330-b79c-090681fcbeeb"",
""CurrentlyEquippedSlot"": -1,
""CurrentlyEquippedSlotIndex"": 0,
""Stamina"": 100
}";
var text = Obfuscation.ObfuscateFileText( original );
text = Obfuscation.UnobfuscateFileText( text );
Assert.AreEqual( original, text );
}
[TestMethod]
public void SelectingUnitialisedCollectionReturnsEmptyList()
{
var results = Sandbank.Select<TestClasses.ReadmeExample>( "players", x => x.Health == 50 );
Assert.AreEqual( 0, results.Count );
}
[TestMethod]
public void NullUIDWorks()
{
var document = new TestClasses.NullUIDClass();
Sandbank.Insert( "nulluidtest", document );
Assert.AreEqual( 32, document.UID.Length );
}
[TestMethod]
public void NoUIDThrowsException()
{
var document = new TestClasses.NoUIDClass();
var e = Assert.ThrowsException<SandbankException>( () => Sandbank.Insert( "nouidtest", document ) );
Assert.AreEqual( $"cannot handle a document without a \"UID\" property - make sure your data " +
"class has a public property called UID, like this: \"[Saved] public string UID { get; set; }\"", e.Message );
}
[TestMethod]
public void CantPutDifferentClassTypesInSameCollection()
{
var document1 = new TestClasses.ValidClass1();
Sandbank.Insert( "test2", document1 );
var document2 = new TestClasses.ValidClass2();
var e = Assert.ThrowsException<SandbankException>( () => Sandbank.Insert( "test2", document2 ) );
Assert.AreEqual( "there is no registered instance pool for the type TestClasses+ValidClass2 - " +
"are you using the wrong class type for this collection?", e.Message );
}
[TestMethod]
public void CopySavedData()
{
var document1 = new ClassWithNonSavedProperty();
document1.Health = 50;
document1.Name = "Steve";
var document2 = new ClassWithNonSavedProperty();
Assert.AreEqual( 0, document2.Health );
Assert.AreEqual( null, document2.Name );
Sandbank.CopySavedData<ClassWithNonSavedProperty>( document1, document2 );
Assert.AreEqual( 50, document2.Health );
Assert.AreEqual( null, document2.Name );
}
[TestMethod]
public void CopySavedData_WorksForAutoSavedProperties()
{
var document1 = new AutoSavedReadmeExample();
document1.Health = 50;
document1.Name = "Steve";
document1.UID = "blahblah";
document1.Items = new List<string>{ "banana", "gun", "shoe" };
var document2 = new AutoSavedReadmeExample();
Assert.AreEqual( 0, document2.Health );
Assert.AreEqual( null, document2.Name );
Assert.AreEqual( null, document2.UID );
Assert.AreEqual( 0, document2.Items.Count );
Sandbank.CopySavedData<AutoSavedReadmeExample>( document1, document2 );
Assert.AreEqual( 50, document2.Health );
Assert.AreEqual( "Steve", document2.Name );
Assert.AreEqual( "blahblah", document2.UID );
Assert.AreEqual( 3, document2.Items.Count );
}
[TestMethod]
public void CantGetDifferentClassTypesFromSameCollection()
{
var document1 = new TestClasses.ValidClass1();
document1.Health = 50;
Sandbank.Insert( "test3", document1 );
var e = Assert.ThrowsException<InvalidCastException>(
() => Sandbank.SelectOneWithID<TestClasses.ValidClass1Copy>( "test3", document1.UID ) );
Assert.AreEqual( "Unable to cast object of type 'ValidClass1' to type 'ValidClass1Copy'.",
e.Message );
}
[TestMethod]
public void ReadmeExampleWorks()
{
var readmeExample = new TestClasses.ReadmeExample();
Assert.AreEqual( null, readmeExample.UID );
readmeExample.Health = 100;
readmeExample.Name = "Bob";
Sandbank.Insert( "players", readmeExample );
Assert.AreEqual( 32, readmeExample.UID.Length );
var playerWith100Health = Sandbank.SelectOne<TestClasses.ReadmeExample>( "players",
x => x.Health == 100 );
Assert.AreEqual( "Bob", playerWith100Health.Name );
Sandbank.DeleteWithID<TestClasses.ReadmeExample>( "players", playerWith100Health.UID );
}
[TestMethod]
public void AutoSavedWorks()
{
var data = new AutoSavedReadmeExample();
data.Health = 57;
data.UID = "91246385";
// Mock all this since codegen doesn't seem to work during tests.
var property = new Sandbox.WrappedPropertySet<float>()
{
Setter = ( float value ) => data.Health = value,
Value = 57,
Object = data,
PropertyName = "Health",
Attributes = new Attribute[]
{
new AutoSaved("example")
}
};
SandbankAutoSavedEventHandler.AutoSave( property );
var fetchedData = Sandbank.Select<AutoSavedReadmeExample>( "example", x => x.Health == 57 );
Assert.AreEqual( 1, fetchedData.Count );
Assert.AreEqual( 8, fetchedData[0].UID.Length );
}
[TestMethod]
public void SavingAndLoadingWorksWithObfuscation()
{
ConfigController.OBFUSCATE_FILES = true;
var readmeExample = new TestClasses.ReadmeExample();
Assert.AreEqual( null, readmeExample.UID );
readmeExample.Health = 100;
readmeExample.Name = "Bob";
Sandbank.Insert( "players", readmeExample );
Assert.AreEqual( 32, readmeExample.UID.Length );
var playerWith100Health = Sandbank.SelectOne<TestClasses.ReadmeExample>( "players",
x => x.Health == 100 );
Assert.AreEqual( "Bob", playerWith100Health.Name );
Sandbank.DeleteWithID<TestClasses.ReadmeExample>( "players", playerWith100Health.UID );
}
[TestMethod]
public void DatabaseWorksWithoutInitialisation()
{
var readmeExample = new TestClasses.ReadmeExample();
Assert.AreEqual( null, readmeExample.UID );
readmeExample.Health = 100;
readmeExample.Name = "Bob";
Sandbank.Insert( "players", readmeExample );
Assert.AreEqual( 32, readmeExample.UID.Length );
var playerWith100Health = Sandbank.SelectOne<TestClasses.ReadmeExample>( "players",
x => x.Health == 100 );
Assert.AreEqual( "Bob", playerWith100Health.Name );
Sandbank.DeleteWithID<TestClasses.ReadmeExample>( "players", playerWith100Health.UID );
}
[TestMethod]
public void SelectUnsafeReferences_DocumentDoesntChangeAfterNewInsert()
{
var document1 = new TestClasses.ValidClass1();
document1.Health = 70;
Sandbank.Insert( "players", document1 );
var unsafeDocument = Sandbank.SelectUnsafeReferences<TestClasses.ValidClass1>("players",
x => x.Health == 70 ).First();
var safeDocument = Sandbank.SelectOne<TestClasses.ValidClass1>( "players",
x => x.Health == 70 );
safeDocument.Health = 80;
Sandbank.Insert( "players", safeDocument );
Assert.AreEqual( unsafeDocument.Health, 70 );
}
[TestMethod]
public void TestInsertAndSelectOne()
{
Sandbank.Insert<ReadmeExample>( "players", TestData.TestData1 );
Assert.IsFalse( TestData.TestData1.UID.Length <= 10 );
var data = Sandbank.SelectOne<ReadmeExample>( "players", x => x.UID == TestData.TestData1.UID );
Assert.IsFalse( data.Name != TestData.TestData1.Name );
}
[TestMethod]
public void TestInsertManyAndSelect()
{
var players = new List<ReadmeExample>{ TestData.TestData1, TestData.TestData2 };
Sandbank.InsertMany<ReadmeExample>( "players", players );
Assert.IsFalse( players[0].UID.Length <= 10 );
Assert.IsFalse( players[1].UID.Length <= 10 );
var data = Sandbank.Select<ReadmeExample>( "players", x => true );
Assert.IsFalse( data[0].Name != TestData.TestData1.Name && data[0].Name != TestData.TestData2.Name );
Assert.IsFalse( data[1].Name != TestData.TestData1.Name && data[1].Name != TestData.TestData2.Name );
}
[TestMethod]
public void TestSelectOneWithID()
{
Sandbank.Insert<ReadmeExample>( "players", TestData.TestData1 );
Assert.IsFalse( TestData.TestData1.UID.Length <= 10 );
var data = Sandbank.SelectOneWithID<ReadmeExample>( "players", TestData.TestData1.UID );
Assert.IsFalse( data?.Name != TestData.TestData1.Name );
}
[TestMethod]
public void TestDelete()
{
Sandbank.Insert<ReadmeExample>( "players", TestData.TestData1 );
Sandbank.Delete<ReadmeExample>( "players", x => x.UID == TestData.TestData1.UID );
var data = Sandbank.SelectOneWithID<ReadmeExample>( "players", TestData.TestData1.UID );
Assert.IsFalse( data != null );
}
/// <summary>
/// Ensure that when we receive an object from the database, modifying it doesn't
/// also modify the cache.
/// </summary>
[TestMethod]
public void TestReferenceDoesntModifyCache()
{
Sandbank.Insert<ReadmeExample>( "players", TestData.TestData1 );
var data = Sandbank.SelectOneWithID<ReadmeExample>( "players", TestData.TestData1.UID );
data.Level = 999;
data = Sandbank.SelectOneWithID<ReadmeExample>( "players", TestData.TestData1.UID );
Assert.IsFalse( data.Level == 999 );
}
[TestMethod]
public void AutoSavedWorks_MultiThreaded()
{
var objects = new List<AutoSavedReadmeExample>();
for (int i = 0; i < 10; i++ )
{
var data = new AutoSavedReadmeExample();
data.Health = 57;
data.UID = $"siffhdfdgf{i}";
objects.Add( data );
}
var tasks = new List<Task>();
// Make sure there's at least one auto save of each item.
for ( int i = 0; i < 10; i++ )
{
var item = objects[i];
tasks.Add( Task.Run( () =>
{
var property = new Sandbox.WrappedPropertySet<float>()
{
Setter = ( float value ) => item.Health = value,
Value = 57,
Object = item,
PropertyName = "Health",
Attributes = new Attribute[]
{
new AutoSaved("example")
}
};
SandbankAutoSavedEventHandler.AutoSave( property );
} ) );
}
for ( int i = 0; i < 1000; i++ )
{
var item = objects[Random.Shared.Int( 0, 9 )];
tasks.Add( Task.Run( () =>
{
var property = new Sandbox.WrappedPropertySet<float>()
{
Setter = ( float value ) => item.Health = value,
Value = 57,
Object = item,
PropertyName = "Health",
Attributes = new Attribute[]
{
new AutoSaved("example")
}
};
SandbankAutoSavedEventHandler.AutoSave( property );
} ) );
}
Task.WaitAll( tasks.ToArray() );
var fetchedData = Sandbank.Select<AutoSavedReadmeExample>( "example", x => x.Health == 57 );
Assert.AreEqual( 10, fetchedData.Count );
}
[TestMethod]
public void TestSpammingShutdownAndInitialise_DoesntCorruptData()
{
const int documents = 100;
Sandbank.Insert<ReadmeExample>( "players", new ReadmeExample()
{
UID = "",
Health = 100,
Name = "TestPlayer1",
Level = 10,
LastPlayTime = DateTime.UtcNow,
Items = new() { "gun", "frog", "banana" }
} );
// Warm the pool up to avoid console spam about not being able to load objects from the pool.
Task.Delay( 4000 ).GetAwaiter().GetResult();
var data = new List<ReadmeExample>();
for ( int i = 0; i < documents - 1; i++ )
{
data.Add( new ReadmeExample()
{
UID = "",
Health = 100,
Name = "TestPlayer1",
Level = 10,
LastPlayTime = DateTime.UtcNow,
Items = new() { "gun", "frog", "banana" }
} );
}
Sandbank.InsertMany<ReadmeExample>( "players", data );
Assert.AreEqual( documents, Sandbank.Select<ReadmeExample>( "players", x => x.Health == 100 ).Count() );
var tasks = new List<Task>();
for ( int i = 0; i < 100; i++ )
{
tasks.Add( Task.Run( InitialisationController.Initialise ) );
tasks.Add( Task.Run( Sandbank.Shutdown ) );
}
Task.WaitAll( tasks.ToArray() );
InitialisationController.Initialise();
Assert.AreEqual( documents, Sandbank.Select<ReadmeExample>( "players", x => x.Health == 100 ).Count() );
}
[TestMethod]
public void TestChangingTypeDefinition_DoesntLoseData()
{
Cache.DisableCacheWriting();
var document = new ReadmeExample()
{
UID = "",
Health = 100,
Name = "TestPlayer1",
Level = 10,
Items = new() { "gun", "frog", "banana" }
};
Sandbank.Insert<ReadmeExample>( "players", document );
var playerDocument = Sandbank.SelectOneWithID<ReadmeExample>( "players", document.UID );
Assert.AreEqual( 100, playerDocument.Health );
Assert.AreEqual( "TestPlayer1", playerDocument.Name );
Assert.AreEqual( 10, playerDocument.Level );
Assert.AreEqual( "gun", playerDocument.Items[0] );
Assert.AreEqual( "frog", playerDocument.Items[1] );
Assert.AreEqual( "banana", playerDocument.Items[2] );
// Force write this so we have it saved to file.
Cache.ForceFullWrite();
// Let's wipe the cache to remove any trace of this class, this will stop the data being
// written to disk when we shutdown the database in a moment.
Cache.WipeCaches();
// Overwrite with a document with different fields. We are checking that the other
// fields are not lost.
var smallerDocument = new ReadmeExampleWithFewerFields()
{
UID = document.UID,
Health = 50,
};
var ovewriteDocument =
new Document( smallerDocument, typeof(ReadmeExampleWithFewerFields), false, "players" );
// Now overwrite the data.
FileController.SaveDocument( ovewriteDocument );
// Shutdown in order to fully clear and re-fetch data and caches.
Sandbank.Shutdown().GetAwaiter().GetResult();
InitialisationController.Initialise();
// Now load the data using the original type - all the other data should be there, other
// than the changed health which was overwritten.
var finalDocument = Sandbank.SelectOneWithID<ReadmeExample>( "players", document.UID );
Assert.AreEqual( 50, finalDocument.Health );
Assert.AreEqual( "TestPlayer1", finalDocument.Name );
Assert.AreEqual( 10, finalDocument.Level );
Assert.AreEqual( "gun", finalDocument.Items[0] );
Assert.AreEqual( "frog", finalDocument.Items[1] );
Assert.AreEqual( "banana", finalDocument.Items[2] );
}
[TestMethod]
public void TestRestartingDatabase_DoesntCorruptData()
{
const int documents = 100;
Sandbank.Insert<ReadmeExample>( "players", new ReadmeExample()
{
UID = "",
Health = 100,
Name = "TestPlayer1",
Level = 10,
LastPlayTime = DateTime.UtcNow,
Items = new() { "gun", "frog", "banana" }
} );
// Warm the pool up to avoid console spam about not being able to load objects from the pool.
Task.Delay( 4000 ).GetAwaiter().GetResult();
var data = new List<ReadmeExample>();
for ( int i = 0; i < documents - 1; i++ )
{
data.Add( new ReadmeExample()
{
UID = "",
Health = 100,
Name = "TestPlayer1",
Level = 10,
LastPlayTime = DateTime.UtcNow,
Items = new() { "gun", "frog", "banana" }
} );
}
Sandbank.InsertMany<ReadmeExample>( "players", data );
Assert.AreEqual( documents, Sandbank.Select<ReadmeExample>( "players", x => x.Health == 100 ).Count() );
Sandbank.Shutdown().GetAwaiter().GetResult();
InitialisationController.Initialise();
Assert.AreEqual( documents, Sandbank.Select<ReadmeExample>( "players", x => x.Health == 100 ).Count() );
}
[TestMethod]
public void TestDeleteWithID()
{
Sandbank.Insert<ReadmeExample>( "players", TestData.TestData1 );
Sandbank.DeleteWithID<ReadmeExample>( "players", TestData.TestData1.UID );
var data = Sandbank.SelectOneWithID<ReadmeExample>( "players", TestData.TestData1.UID );
Assert.IsFalse( data != null );
}
[TestMethod]
public void TestAny()
{
Sandbank.Insert<ReadmeExample>( "players", TestData.TestData1 );
Assert.IsFalse( !Sandbank.Any<ReadmeExample>( "players", x => x.Level == TestData.TestData1.Level ) );
}
[TestMethod]
public void TestAnyWithID()
{
Sandbank.Insert<ReadmeExample>( "players", TestData.TestData1 );
Assert.IsFalse( !Sandbank.AnyWithID<ReadmeExample>( "players", TestData.TestData1.UID ) );
}
[TestMethod]
public void TestShutdown()
{
TestData.TestData1.UID = "";
Sandbank.Insert<ReadmeExample>( "players", TestData.TestData1 );
var collection = Cache.GetCollectionByName<ReadmeExample>( "players", false );
Assert.AreEqual( 1, Cache.GetDocumentsAwaitingWriteCount() );
Sandbank.Shutdown().GetAwaiter().GetResult();
Assert.AreEqual( 0, Cache.GetDocumentsAwaitingWriteCount() );
}
[TestMethod]
public void TestConcurrencySafety()
{
List<Task> tasks = new();
for ( int i = 0; i < 10; i++ )
{
tasks.Add( Task.Run( () =>
{
var data = new ReadmeExample()
{
UID = "",
Health = Game.Random.Next( 101 ),
Name = "TestPlayer1",
Level = 10,
LastPlayTime = DateTime.UtcNow,
Items = new() { "gun", "frog", "banana" }
};
Sandbank.InsertMany<ReadmeExample>( "players", new ReadmeExample[] { data, data, data, data } );
Sandbank.Insert<ReadmeExample>( "players", data );
var results = Sandbank.Select<ReadmeExample>( "players", x => x.Health > 90 );
if ( results.Count > 0 )
{
Sandbank.SelectOneWithID<ReadmeExample>( "players", results[0].UID );
Sandbank.DeleteWithID<ReadmeExample>( "players", results[0].UID );
}
Sandbank.Delete<ReadmeExample>( "players", x => x.Health <= 20 );
Sandbank.Any<ReadmeExample>( "players", x => x.Name == "Tim" );
} ) );
}
Task.WaitAll( tasks.ToArray() );
}
[TestMethod]
public void TestConcurrencySafety2()
{
List<Task> tasks = new();
List<ReadmeExample> loadsOfData = new();
for ( int i = 0; i < 10000; i++ )
{
loadsOfData.Add( new ReadmeExample()
{
UID = "",
Health = 100,
Name = "TestPlayer",
Level = Game.Random.Next( 10 ),
LastPlayTime = DateTime.UtcNow,
Items = new() { "gun", "frog", "banana" }
} );
}
for ( int i = 0; i < 10; i++ )
{
tasks.Add( Task.Run( () =>
{
for ( int j = 0; j < 10000; j++ )
{
var data = new ReadmeExample()
{
UID = "",
Health = 100,
Name = "TestPlayer",
Level = 10,
LastPlayTime = DateTime.UtcNow,
Items = new() { "gun", "frog", "banana" }
};
Sandbank.Insert<ReadmeExample>( "players", data );
Sandbank.Insert<ReadmeExample>( "players_two", data );
}
} ) );
tasks.Add( Task.Run( () =>
{
Sandbank.InsertMany<ReadmeExample>( "players", loadsOfData );
Sandbank.InsertMany<ReadmeExample>( "players_two", loadsOfData );
} ) );
tasks.Add( Task.Run( () =>
{
Sandbank.Select<ReadmeExample>( "players", x => x.Health == 100 );
Sandbank.Select<ReadmeExample>( "players_two", x => x.Name == "TestPlayer" );
} ) );
tasks.Add( Task.Run( () =>
{
Sandbank.Delete<ReadmeExample>( "players", x => x.Level == 5 || x.Level == 2 );
Sandbank.Delete<ReadmeExample>( "players_two", x => x.Level == 5 || x.Level == 2 );
} ) );
}
Task.WaitAll( tasks.ToArray() );
}
[TestMethod]
public void TestConcurrencySafety_SpamCollections()
{
List<Task> tasks = new();
List<ReadmeExample> loadsOfData = new();
for ( int i = 0; i < 100; i++ )
{
loadsOfData.Add( new ReadmeExample()
{
UID = "",
Health = 100,
Name = "TestPlayer",
Level = Game.Random.Next( 10 ),
LastPlayTime = DateTime.UtcNow,
Items = new() { "gun", "frog", "banana" }
} );
}
for ( int x = 0; x < 10; x++ )
{
for ( int i = 0; i < 100; i++ )
{
string collection = "collection" + i;
tasks.Add( Task.Run( () =>
{
for ( int i = 0; i < 100; i++ )
{
Sandbank.Insert<ReadmeExample>( collection, loadsOfData[i] );
}
} ) );
tasks.Add( Task.Run( () =>
{
Sandbank.Delete<ReadmeExample>( collection, x => x.Level == 5 || x.Level == 2 );
} ) );
}
}
Task.WaitAll( tasks.ToArray() );
}
}
global using Microsoft.VisualStudio.TestTools.UnitTesting;
[TestClass]
public class TestInit
{
[AssemblyInitialize]
public static void ClassInitialize( TestContext context )
{
Sandbox.Application.InitUnitTest();
}
}
global using Microsoft.VisualStudio.TestTools.UnitTesting;
[TestClass]
public class TestInit
{
[AssemblyInitialize]
public static void ClassInitialize( TestContext context )
{
Sandbox.Application.InitUnitTest();
}
}