mirror of
https://github.com/clockworklabs/SpacetimeDB.git
synced 2026-05-06 15:49:35 -04:00
C# SDK tests (#706)
* Add C# SDK tests * Add memoization * Increase timeout * Mark module_bindings as LF * Regenerate from Rust again * Sort tables & reducers for determinism * cargo fmt * Lint & fmt fixups * Lint fixups * Allow dirs ending in .wasm
This commit is contained in:
+1
-1
@@ -1 +1 @@
|
||||
**/module_bindings/** linguist-generated=true
|
||||
**/module_bindings/** linguist-generated=true eol=lf
|
||||
|
||||
@@ -271,8 +271,13 @@ public class Module : IIncrementalGenerator
|
||||
tableNames.Combine(addReducers),
|
||||
(context, tuple) =>
|
||||
{
|
||||
var tableNames = tuple.Left;
|
||||
var addReducers = tuple.Right;
|
||||
// Sort tables and reducers by name to match Rust behaviour.
|
||||
// Not really important outside of testing, but for testing
|
||||
// it matters because we commit module-bindings
|
||||
// so they need to match 1:1 between different langs.
|
||||
var tableNames = tuple.Left.Sort();
|
||||
var addReducers = tuple.Right.Sort((a, b) => a.Name.CompareTo(b.Name));
|
||||
// Don't generate the FFI boilerplate if there are no tables or reducers.
|
||||
if (tableNames.IsEmpty && addReducers.IsEmpty)
|
||||
return;
|
||||
context.AddSource(
|
||||
|
||||
@@ -137,7 +137,11 @@ pub async fn exec(mut config: Config, args: &ArgMatches) -> Result<(), anyhow::E
|
||||
query_params.push(("trace_log", "true"));
|
||||
}
|
||||
|
||||
let path_to_wasm = crate::tasks::build(path_to_project, skip_clippy, build_debug)?;
|
||||
let path_to_wasm = if !path_to_project.is_dir() && path_to_project.extension().map_or(false, |ext| ext == "wasm") {
|
||||
path_to_project.clone()
|
||||
} else {
|
||||
crate::tasks::build(path_to_project, skip_clippy, build_debug)?
|
||||
};
|
||||
let program_bytes = fs::read(path_to_wasm)?;
|
||||
println!(
|
||||
"Uploading to {} => {}",
|
||||
|
||||
@@ -56,7 +56,7 @@ impl TestCounter {
|
||||
let lock = self.inner.lock().expect("TestCounterInner Mutex is poisoned");
|
||||
let (lock, timeout_result) = self
|
||||
.wait_until_done
|
||||
.wait_timeout_while(lock, Duration::from_secs(5), |inner| {
|
||||
.wait_timeout_while(lock, Duration::from_secs(30), |inner| {
|
||||
inner.outcomes.len() != inner.registered.len()
|
||||
})
|
||||
.expect("TestCounterInner Mutex is poisoned");
|
||||
|
||||
+135
-137
@@ -1,141 +1,139 @@
|
||||
use spacetimedb_testing::sdk::Test;
|
||||
macro_rules! declare_tests_with_suffix {
|
||||
($lang:ident, $suffix:literal) => {
|
||||
mod $lang {
|
||||
use spacetimedb_testing::sdk::Test;
|
||||
|
||||
const MODULE: &str = "sdk-test";
|
||||
const CLIENT: &str = concat!(env!("CARGO_MANIFEST_DIR"), "/tests/test-client");
|
||||
const MODULE: &str = concat!("sdk-test", $suffix);
|
||||
const CLIENT: &str = concat!(env!("CARGO_MANIFEST_DIR"), "/tests/test-client");
|
||||
|
||||
fn make_test(subcommand: &str) -> Test {
|
||||
Test::builder()
|
||||
.with_name(subcommand)
|
||||
.with_module(MODULE)
|
||||
.with_client(CLIENT)
|
||||
.with_language("rust")
|
||||
.with_bindings_dir("src/module_bindings")
|
||||
.with_compile_command("cargo build")
|
||||
.with_run_command(format!("cargo run -- {}", subcommand))
|
||||
.build()
|
||||
fn make_test(subcommand: &str) -> Test {
|
||||
Test::builder()
|
||||
.with_name(subcommand)
|
||||
.with_module(MODULE)
|
||||
.with_client(CLIENT)
|
||||
.with_language("rust")
|
||||
.with_bindings_dir("src/module_bindings")
|
||||
.with_compile_command("cargo build")
|
||||
.with_run_command(format!("cargo run -- {}", subcommand))
|
||||
.build()
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn insert_primitive() {
|
||||
make_test("insert_primitive").run();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn delete_primitive() {
|
||||
make_test("delete_primitive").run();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn update_primitive() {
|
||||
make_test("update_primitive").run();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn insert_identity() {
|
||||
make_test("insert_identity").run();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn delete_identity() {
|
||||
make_test("delete_identity").run();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn update_identity() {
|
||||
make_test("delete_identity").run();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn insert_address() {
|
||||
make_test("insert_address").run();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn delete_address() {
|
||||
make_test("delete_address").run();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn update_address() {
|
||||
make_test("delete_address").run();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn on_reducer() {
|
||||
make_test("on_reducer").run();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn fail_reducer() {
|
||||
make_test("fail_reducer").run();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn insert_vec() {
|
||||
make_test("insert_vec").run();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn insert_simple_enum() {
|
||||
make_test("insert_simple_enum").run();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn insert_enum_with_payload() {
|
||||
make_test("insert_enum_with_payload").run();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn insert_long_table() {
|
||||
make_test("insert_long_table").run();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn resubscribe() {
|
||||
make_test("resubscribe").run();
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic]
|
||||
fn should_fail() {
|
||||
make_test("should_fail").run();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn reauth() {
|
||||
make_test("reauth_part_1").run();
|
||||
make_test("reauth_part_2").run();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn reconnect_same_address() {
|
||||
make_test("reconnect_same_address").run();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn connect_disconnect_callbacks() {
|
||||
Test::builder()
|
||||
.with_name(concat!("connect_disconnect_callback_", stringify!($lang)))
|
||||
.with_module(concat!("sdk-test-connect-disconnect", $suffix))
|
||||
.with_client(concat!(
|
||||
env!("CARGO_MANIFEST_DIR"),
|
||||
"/tests/connect_disconnect_client"
|
||||
))
|
||||
.with_language("rust")
|
||||
.with_bindings_dir("src/module_bindings")
|
||||
.with_compile_command("cargo build")
|
||||
.with_run_command("cargo run")
|
||||
.build()
|
||||
.run();
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn insert_primitive() {
|
||||
make_test("insert_primitive").run();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn delete_primitive() {
|
||||
make_test("delete_primitive").run();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn update_primitive() {
|
||||
make_test("update_primitive").run();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn insert_identity() {
|
||||
make_test("insert_identity").run();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn delete_identity() {
|
||||
make_test("delete_identity").run();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn update_identity() {
|
||||
make_test("delete_identity").run();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn insert_address() {
|
||||
make_test("insert_address").run();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn delete_address() {
|
||||
make_test("delete_address").run();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn update_address() {
|
||||
make_test("delete_address").run();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn on_reducer() {
|
||||
make_test("on_reducer").run();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn fail_reducer() {
|
||||
make_test("fail_reducer").run();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn insert_vec() {
|
||||
make_test("insert_vec").run();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn insert_simple_enum() {
|
||||
make_test("insert_simple_enum").run();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn insert_enum_with_payload() {
|
||||
make_test("insert_enum_with_payload").run();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn insert_long_table() {
|
||||
make_test("insert_long_table").run();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn resubscribe() {
|
||||
make_test("resubscribe").run();
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic]
|
||||
fn should_fail() {
|
||||
make_test("should_fail").run();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn reauth() {
|
||||
make_test("reauth_part_1").run();
|
||||
make_test("reauth_part_2").run();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn reconnect_same_address() {
|
||||
make_test("reconnect_same_address").run();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn connect_disconnect_callbacks() {
|
||||
Test::builder()
|
||||
.with_name("connect_disconnect_callback")
|
||||
.with_module("sdk-test-connect-disconnect")
|
||||
.with_client(concat!(env!("CARGO_MANIFEST_DIR"), "/tests/connect_disconnect_client"))
|
||||
.with_language("rust")
|
||||
.with_bindings_dir("src/module_bindings")
|
||||
.with_compile_command("cargo build")
|
||||
.with_run_command("cargo run")
|
||||
.build()
|
||||
.run();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn connect_disconnect_callbacks_csharp() {
|
||||
Test::builder()
|
||||
.with_name("connect_disconnect_callback_csharp")
|
||||
.with_module("sdk-test-connect-disconnect-cs")
|
||||
.with_client(concat!(env!("CARGO_MANIFEST_DIR"), "/tests/connect_disconnect_client"))
|
||||
.with_language("rust")
|
||||
.with_bindings_dir("src/module_bindings")
|
||||
.with_compile_command("cargo build")
|
||||
.with_run_command("cargo run")
|
||||
.build()
|
||||
.run();
|
||||
}
|
||||
declare_tests_with_suffix!(rust, "");
|
||||
declare_tests_with_suffix!(csharp, "-cs");
|
||||
|
||||
+112
-82
@@ -1,12 +1,13 @@
|
||||
use duct::cmd;
|
||||
use lazy_static::lazy_static;
|
||||
use rand::distributions::{Alphanumeric, DistString};
|
||||
use std::collections::HashMap;
|
||||
use std::fs::create_dir_all;
|
||||
use std::sync::Mutex;
|
||||
use std::thread::JoinHandle;
|
||||
use std::{collections::HashSet, fs::create_dir_all, sync::Mutex};
|
||||
|
||||
use crate::invoke_cli;
|
||||
use crate::modules::{module_path, CompilationMode, CompiledModule};
|
||||
use std::path::Path;
|
||||
use crate::modules::{CompilationMode, CompiledModule};
|
||||
use tempfile::TempDir;
|
||||
|
||||
pub fn ensure_standalone_process() {
|
||||
@@ -34,41 +35,9 @@ pub fn ensure_standalone_process() {
|
||||
}
|
||||
}
|
||||
|
||||
lazy_static! {
|
||||
/// An exclusive lock which ensures we only run `spacetime generate` once for each target directory.
|
||||
///
|
||||
/// Without this lock, if multiple `Test`s ran concurrently in the same process
|
||||
/// with the same `client_project` and `generate_subdir`,
|
||||
/// the test harness would run `spacetime generate` multiple times concurrently,
|
||||
/// each of which would remove and re-populate the bindings directory,
|
||||
/// potentially sweeping them out from under a compile or run process.
|
||||
///
|
||||
/// This lock ensures that only one `spacetime generate` process runs at a time,
|
||||
/// and the `HashSet` ensures that we run `spacetime generate` only once for each output directory.
|
||||
///
|
||||
/// Circumstances where this will still break:
|
||||
/// - If multiple tests want to use the same client_project/generate_subdir pair,
|
||||
/// but for different modules' bindings, only one module's bindings will ever be generated.
|
||||
/// If you need bindings for multiple different modules, put them in different subdirs.
|
||||
/// - If multiple distinct test harness processes run concurrently,
|
||||
/// they will encounter the race condition described above,
|
||||
/// because the `BINDINGS_GENERATED` lock is not shared between harness processes.
|
||||
/// Running multiple test harness processes concurrently will break anyways
|
||||
/// because each will try to run `spacetime start` as a subprocess and will therefore
|
||||
/// contend over port 3000.
|
||||
/// Prefer constructing multiple `Test`s and `Test::run`ing them
|
||||
/// from within the same harness process.
|
||||
//
|
||||
// I (pgoldman 2023-09-11) considered, as an alternative to this lock,
|
||||
// having `Test::run` copy the `client_project` into a fresh temporary directory.
|
||||
// That would be more complicated, as we'd need to re-write dependencies
|
||||
// on the client language's SpacetimeDB SDK to use a local absolute path.
|
||||
// Doing so portably across all our SDK languages seemed infeasible.
|
||||
static ref BINDINGS_GENERATED: Mutex<HashSet<String>> = Mutex::new(HashSet::new());
|
||||
}
|
||||
|
||||
pub struct Test {
|
||||
/// A human-readable name for this test.
|
||||
#[allow(dead_code)] // TODO: should we just remove this now that it's unused?
|
||||
name: String,
|
||||
|
||||
/// Must name a module in the SpacetimeDB/modules directory.
|
||||
@@ -107,23 +76,23 @@ impl Test {
|
||||
pub fn builder() -> TestBuilder {
|
||||
TestBuilder::default()
|
||||
}
|
||||
pub fn run(&self) {
|
||||
pub fn run(self) {
|
||||
ensure_standalone_process();
|
||||
|
||||
let compiled = CompiledModule::compile(&self.module_name, CompilationMode::Debug);
|
||||
let wasm_file = compile_module(&self.module_name);
|
||||
|
||||
generate_bindings(
|
||||
&self.generate_language,
|
||||
compiled.path(),
|
||||
&wasm_file,
|
||||
&self.client_project,
|
||||
&self.generate_subdir,
|
||||
);
|
||||
|
||||
compile_client(&self.compile_command, &self.client_project, &self.name);
|
||||
compile_client(&self.compile_command, &self.client_project);
|
||||
|
||||
let db_name = publish_module(&self.module_name);
|
||||
let db_name = publish_module(&wasm_file);
|
||||
|
||||
run_client(&self.run_command, &self.client_project, &db_name, &self.name);
|
||||
run_client(&self.run_command, &self.client_project, &db_name);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -143,43 +112,96 @@ fn random_module_name() -> String {
|
||||
Alphanumeric.sample_string(&mut rand::thread_rng(), 16)
|
||||
}
|
||||
|
||||
fn publish_module(module: &str) -> String {
|
||||
macro_rules! memoized {
|
||||
(|$key:ident: $key_ty:ty| -> $value_ty:ty $body:block) => {{
|
||||
static MEMOIZED: Mutex<Option<HashMap<$key_ty, $value_ty>>> = Mutex::new(None);
|
||||
|
||||
MEMOIZED
|
||||
.lock()
|
||||
.unwrap()
|
||||
.get_or_insert_with(HashMap::new)
|
||||
.entry($key)
|
||||
.or_insert_with_key(|$key| -> $value_ty { $body })
|
||||
.clone()
|
||||
}};
|
||||
}
|
||||
|
||||
// Note: this function is memoized to ensure we compile each module only once.
|
||||
// Without this lock, if multiple `Test`s ran concurrently in the same process,
|
||||
// the test harness would compile each module multiple times concurrently,
|
||||
// which is bad both for performance reasons as well as can lead to errors
|
||||
// with toolchains like .NET which don't expect parallel invocations
|
||||
// of their build tools on the same project folder.
|
||||
fn compile_module(module: &str) -> String {
|
||||
let module = module.to_owned();
|
||||
|
||||
memoized!(|module: String| -> String {
|
||||
let module = CompiledModule::compile(module, CompilationMode::Debug);
|
||||
module.path().to_str().unwrap().to_owned()
|
||||
})
|
||||
}
|
||||
|
||||
// Note: this function does not memoize because we want each test to publish the same
|
||||
// module as a separate clean database instance for isolation purposes.
|
||||
fn publish_module(wasm_file: &str) -> String {
|
||||
let name = random_module_name();
|
||||
invoke_cli(&[
|
||||
"publish",
|
||||
"--debug",
|
||||
"--project-path",
|
||||
module_path(module).to_str().unwrap(),
|
||||
wasm_file,
|
||||
"--skip_clippy",
|
||||
&name,
|
||||
]);
|
||||
|
||||
name
|
||||
}
|
||||
|
||||
fn generate_bindings(language: &str, path: &Path, client_project: &str, generate_subdir: &str) {
|
||||
let generate_dir = format!("{}/{}", client_project, generate_subdir);
|
||||
/// Note: this function is memoized to ensure we only run `spacetime generate` once for each target directory.
|
||||
///
|
||||
/// Without this lock, if multiple `Test`s ran concurrently in the same process
|
||||
/// with the same `client_project` and `generate_subdir`,
|
||||
/// the test harness would run `spacetime generate` multiple times concurrently,
|
||||
/// each of which would remove and re-populate the bindings directory,
|
||||
/// potentially sweeping them out from under a compile or run process.
|
||||
///
|
||||
/// This lock ensures that only one `spacetime generate` process runs at a time,
|
||||
/// and the `HashSet` ensures that we run `spacetime generate` only once for each output directory.
|
||||
///
|
||||
/// Circumstances where this will still break:
|
||||
/// - If multiple tests want to use the same client_project/generate_subdir pair,
|
||||
/// but for different modules' bindings, only one module's bindings will ever be generated.
|
||||
/// If you need bindings for multiple different modules, put them in different subdirs.
|
||||
/// - If multiple distinct test harness processes run concurrently,
|
||||
/// they will encounter the race condition described above,
|
||||
/// because the `BINDINGS_GENERATED` lock is not shared between harness processes.
|
||||
/// Running multiple test harness processes concurrently will break anyways
|
||||
/// because each will try to run `spacetime start` as a subprocess and will therefore
|
||||
/// contend over port 3000.
|
||||
/// Prefer constructing multiple `Test`s and `Test::run`ing them
|
||||
/// from within the same harness process.
|
||||
//
|
||||
// I (pgoldman 2023-09-11) considered, as an alternative to this lock,
|
||||
// having `Test::run` copy the `client_project` into a fresh temporary directory.
|
||||
// That would be more complicated, as we'd need to re-write dependencies
|
||||
// on the client language's SpacetimeDB SDK to use a local absolute path.
|
||||
// Doing so portably across all our SDK languages seemed infeasible.
|
||||
fn generate_bindings(language: &str, wasm_file: &str, client_project: &str, generate_subdir: &str) {
|
||||
let generate_dir = format!("{client_project}/{generate_subdir}");
|
||||
|
||||
let mut bindings_lock = BINDINGS_GENERATED.lock().expect("BINDINGS_GENERATED Mutex is poisoned");
|
||||
|
||||
// If we've already generated bindings in this directory,
|
||||
// return early.
|
||||
// Otherwise, we'll hold the lock for the duration of the subprocess,
|
||||
// so other tests will wait before overwriting our output.
|
||||
if !bindings_lock.insert(generate_dir.clone()) {
|
||||
return;
|
||||
}
|
||||
|
||||
create_dir_all(&generate_dir).expect("Error creating generate subdir");
|
||||
invoke_cli(&[
|
||||
"generate",
|
||||
"--skip_clippy",
|
||||
"--lang",
|
||||
language,
|
||||
"--wasm-file",
|
||||
path.to_str().unwrap(),
|
||||
"--out-dir",
|
||||
&generate_dir,
|
||||
]);
|
||||
memoized!(|generate_dir: String| -> () {
|
||||
create_dir_all(generate_dir).expect("Error creating generate subdir");
|
||||
invoke_cli(&[
|
||||
"generate",
|
||||
"--debug",
|
||||
"--skip_clippy",
|
||||
"--lang",
|
||||
language,
|
||||
"--wasm-file",
|
||||
wasm_file,
|
||||
"--out-dir",
|
||||
&generate_dir,
|
||||
]);
|
||||
})
|
||||
}
|
||||
|
||||
fn split_command_string(command: &str) -> (&str, Vec<&str>) {
|
||||
@@ -189,36 +211,44 @@ fn split_command_string(command: &str) -> (&str, Vec<&str>) {
|
||||
(exe, args)
|
||||
}
|
||||
|
||||
fn compile_client(compile_command: &str, client_project: &str, test_name: &str) {
|
||||
let (exe, args) = split_command_string(compile_command);
|
||||
// Note: this function is memoized to ensure we only compile each client once.
|
||||
fn compile_client(compile_command: &str, client_project: &str) {
|
||||
let client_project = client_project.to_owned();
|
||||
|
||||
let output = cmd(exe, args)
|
||||
.dir(client_project)
|
||||
.env(TEST_CLIENT_PROJECT_ENV_VAR, client_project)
|
||||
.stderr_to_stdout()
|
||||
.stdout_capture()
|
||||
.unchecked()
|
||||
.run()
|
||||
.expect("Error running compile command");
|
||||
memoized!(|client_project: String| -> () {
|
||||
let (exe, args) = split_command_string(compile_command);
|
||||
|
||||
status_ok_or_panic(output, compile_command, test_name);
|
||||
let output = cmd(exe, args)
|
||||
.dir(client_project)
|
||||
.env(TEST_CLIENT_PROJECT_ENV_VAR, client_project)
|
||||
.stderr_to_stdout()
|
||||
.stdout_capture()
|
||||
.unchecked()
|
||||
.run()
|
||||
.expect("Error running compile command");
|
||||
|
||||
status_ok_or_panic(output, compile_command, "(compiling)");
|
||||
})
|
||||
}
|
||||
|
||||
fn run_client(run_command: &str, client_project: &str, db_name: &str, test_name: &str) {
|
||||
fn run_client(run_command: &str, client_project: &str, db_name: &str) {
|
||||
let (exe, args) = split_command_string(run_command);
|
||||
|
||||
let output = cmd(exe, args)
|
||||
.dir(client_project)
|
||||
.env(TEST_CLIENT_PROJECT_ENV_VAR, client_project)
|
||||
.env(TEST_DB_NAME_ENV_VAR, db_name)
|
||||
.env("RUST_LOG", "trace")
|
||||
.env(
|
||||
"RUST_LOG",
|
||||
"spacetimedb=debug,spacetimedb_client_api=debug,spacetimedb_lib=debug,spacetimedb_standalone=debug",
|
||||
)
|
||||
.stderr_to_stdout()
|
||||
.stdout_capture()
|
||||
.unchecked()
|
||||
.run()
|
||||
.expect("Error running run command");
|
||||
|
||||
status_ok_or_panic(output, run_command, test_name);
|
||||
status_ok_or_panic(output, run_command, "(running)");
|
||||
}
|
||||
|
||||
#[derive(Clone, Default)]
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
bin
|
||||
obj
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,27 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<!-- needs to be exe for initializers to be embedded correctly -->
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<RuntimeIdentifier>wasi-wasm</RuntimeIdentifier>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<WasmDebugLevel>1</WasmDebugLevel>
|
||||
<WasmBuildNative>true</WasmBuildNative>
|
||||
<WasmNativeDebugSymbols>true</WasmNativeDebugSymbols>
|
||||
<WasmNativeStrip>false</WasmNativeStrip>
|
||||
<EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>
|
||||
</PropertyGroup>
|
||||
|
||||
<!--
|
||||
Use local package sources instead of published ones.
|
||||
This makes integration test somewhat differ from production configuration, but
|
||||
at least it simplifies workflow for editing and testing C# code itself.
|
||||
-->
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="../../crates/bindings-csharp/Codegen/Codegen.csproj" OutputItemType="Analyzer" />
|
||||
<ProjectReference Include="../../crates/bindings-csharp/Runtime/Runtime.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
Reference in New Issue
Block a user