Add managed codec DSP and initial control server
This commit is contained in:
@@ -0,0 +1,101 @@
|
||||
using Microsoft.Data.Sqlite;
|
||||
using System.Diagnostics;
|
||||
using VoiceCat.Server.Data;
|
||||
|
||||
namespace VoiceCat.Tests;
|
||||
|
||||
public sealed class AccountStoreTests
|
||||
{
|
||||
[Fact]
|
||||
public void UnsupportedSchemaIsRejectedWithoutCreatingAccountTables()
|
||||
{
|
||||
string path = Path.Combine(Path.GetTempPath(), "voicecat-future-" + Guid.NewGuid().ToString("N") + ".db");
|
||||
try
|
||||
{
|
||||
SQLitePCL.Batteries_V2.Init();
|
||||
using var connection = new SqliteConnection(new SqliteConnectionStringBuilder { DataSource = path, Pooling = false }.ToString());
|
||||
connection.Open();
|
||||
using var command = connection.CreateCommand();
|
||||
command.CommandText = "CREATE TABLE server_meta (key TEXT PRIMARY KEY,value TEXT NOT NULL); INSERT INTO server_meta VALUES ('schema_version','99');";
|
||||
command.ExecuteNonQuery();
|
||||
Assert.Throws<InvalidDataException>(() => new AccountStore(path));
|
||||
command.CommandText = "SELECT COUNT(*) FROM sqlite_master WHERE name='accounts'";
|
||||
Assert.Equal(0L, command.ExecuteScalar());
|
||||
command.CommandText = "SELECT value FROM server_meta WHERE key='schema_version'";
|
||||
Assert.Equal("99", command.ExecuteScalar());
|
||||
}
|
||||
finally { File.Delete(path); File.Delete(path + "-wal"); File.Delete(path + "-shm"); }
|
||||
}
|
||||
|
||||
[NativeDatabaseFact]
|
||||
public async Task ExistingCppDatabaseAndManagedAccountsWorkInBothImplementations()
|
||||
{
|
||||
string directory = Path.Combine(Path.GetTempPath(), "voicecat-import-" + Guid.NewGuid().ToString("N"));
|
||||
Directory.CreateDirectory(directory);
|
||||
string path = Path.Combine(directory, "voicecat.db");
|
||||
try
|
||||
{
|
||||
await RunOracleAsync("create", path);
|
||||
using (var store = new AccountStore(path))
|
||||
{
|
||||
Account account = Assert.IsType<Account>(await store.AuthenticateAsync("legacy", "legacy password"));
|
||||
Assert.True(account.IsAdmin);
|
||||
var channel = Assert.Single(store.LoadChannels());
|
||||
Assert.Equal("Preserved native topic", channel.Topic);
|
||||
Assert.Equal(7U, channel.MaxUsers);
|
||||
Assert.Equal(32000U, channel.Audio.BitrateBps);
|
||||
await store.CreateAccountAsync("managed", "managed password", true);
|
||||
}
|
||||
await RunOracleAsync("verify", path);
|
||||
}
|
||||
finally { Directory.Delete(directory, true); }
|
||||
}
|
||||
|
||||
private static async Task RunOracleAsync(string mode, string path)
|
||||
{
|
||||
var start = new ProcessStartInfo(Environment.GetEnvironmentVariable("VOICECAT_DATABASE_ORACLE")!) { UseShellExecute = false, CreateNoWindow = true };
|
||||
start.ArgumentList.Add(mode);
|
||||
start.ArgumentList.Add(path);
|
||||
using var process = Process.Start(start)!;
|
||||
using var timeout = new CancellationTokenSource(TimeSpan.FromSeconds(30));
|
||||
try { await process.WaitForExitAsync(timeout.Token); Assert.Equal(0, process.ExitCode); }
|
||||
finally { if (!process.HasExited) { process.Kill(true); await process.WaitForExitAsync(); } }
|
||||
}
|
||||
|
||||
private sealed class NativeDatabaseFactAttribute : FactAttribute
|
||||
{
|
||||
public NativeDatabaseFactAttribute()
|
||||
{
|
||||
if (string.IsNullOrEmpty(Environment.GetEnvironmentVariable("VOICECAT_DATABASE_ORACLE"))) Skip = "Set VOICECAT_DATABASE_ORACLE to the native database oracle.";
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task AccountsSurviveRestartAndFailedAuthDoesNotChangeLastLogin()
|
||||
{
|
||||
string directory = Path.Combine(Path.GetTempPath(), "voicecat-db-" + Guid.NewGuid().ToString("N"));
|
||||
Directory.CreateDirectory(directory);
|
||||
string path = Path.Combine(directory, "voicecat.db");
|
||||
try
|
||||
{
|
||||
Account account;
|
||||
using (var store = new AccountStore(path)) account = await store.CreateAccountAsync("admin'", "secret", true);
|
||||
using (var store = new AccountStore(path))
|
||||
{
|
||||
Assert.Null(await store.AuthenticateAsync("admin'", "wrong"));
|
||||
Assert.Null(await store.AuthenticateAsync("missing", "secret"));
|
||||
using var connection = new SqliteConnection(new SqliteConnectionStringBuilder { DataSource = path, Pooling = false }.ToString());
|
||||
connection.Open();
|
||||
using var command = connection.CreateCommand();
|
||||
command.CommandText = "SELECT last_login FROM accounts WHERE id=$id";
|
||||
command.Parameters.AddWithValue("$id", account.Id);
|
||||
Assert.Equal(0L, command.ExecuteScalar());
|
||||
Account authenticated = Assert.IsType<Account>(await store.AuthenticateAsync("admin'", "secret"));
|
||||
Assert.Equal(account.Id, authenticated.Id);
|
||||
Assert.True(authenticated.IsAdmin);
|
||||
Assert.True(authenticated.LastLogin > 0);
|
||||
}
|
||||
}
|
||||
finally { Directory.Delete(directory, true); }
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user