Files
sqrtspace-dotnet/tests/SqrtSpace.SpaceTime.Tests/Analyzers/LargeAllocationCodeFixTests.cs
2025-07-20 03:41:39 -04:00

427 lines
8.6 KiB
C#

using System.Threading.Tasks;
using Microsoft.CodeAnalysis.CSharp.Testing;
using Microsoft.CodeAnalysis.Testing;
using Microsoft.CodeAnalysis.Testing.Verifiers;
using SqrtSpace.SpaceTime.Analyzers;
using Xunit;
namespace SqrtSpace.SpaceTime.Tests.Analyzers;
public class LargeAllocationCodeFixTests
{
private static async Task VerifyCodeFixAsync(string source, string fixedSource)
{
var test = new CSharpCodeFixTest<LargeAllocationAnalyzer, LargeAllocationCodeFixProvider, XUnitVerifier>
{
TestCode = source,
FixedCode = fixedSource,
ReferenceAssemblies = ReferenceAssemblies.Net.Net60
};
// Add reference to SpaceTime libraries
test.TestState.AdditionalReferences.Add(typeof(SqrtSpace.SpaceTime.Linq.SpaceTimeEnumerable).Assembly);
test.TestState.AdditionalReferences.Add(typeof(SqrtSpace.SpaceTime.Collections.AdaptiveList<>).Assembly);
await test.RunAsync();
}
[Fact]
public async Task ToList_FixesToCheckpointedListAsync()
{
const string source = @"
using System.Linq;
using System.Collections.Generic;
using System.Threading.Tasks;
class TestClass
{
async Task TestMethod()
{
var context = new TestContext();
var list = context.LargeCollection.{|ST001:ToList|}();
}
}
class TestContext
{
public IQueryable<string> LargeCollection { get; set; }
}";
const string fixedSource = @"
using System.Linq;
using System.Collections.Generic;
using System.Threading.Tasks;
using SqrtSpace.SpaceTime.Linq;
class TestClass
{
async Task TestMethod()
{
var context = new TestContext();
var list = await context.LargeCollection.ToCheckpointedListAsync();
}
}
class TestContext
{
public IQueryable<string> LargeCollection { get; set; }
}";
await VerifyCodeFixAsync(source, fixedSource);
}
[Fact]
public async Task OrderBy_FixesToOrderByExternal()
{
const string source = @"
using System.Linq;
class TestClass
{
void TestMethod()
{
var context = new AppContext();
var sorted = context.Users.{|ST001:OrderBy|}(u => u.Name).ToList();
}
}
class AppContext
{
public IQueryable<User> Users { get; set; }
}
class User
{
public string Name { get; set; }
}";
const string fixedSource = @"
using System.Linq;
using SqrtSpace.SpaceTime.Linq;
class TestClass
{
void TestMethod()
{
var context = new AppContext();
var sorted = context.Users.OrderByExternal(u => u.Name).ToList();
}
}
class AppContext
{
public IQueryable<User> Users { get; set; }
}
class User
{
public string Name { get; set; }
}";
await VerifyCodeFixAsync(source, fixedSource);
}
[Fact]
public async Task OrderByDescending_FixesToOrderByDescendingExternal()
{
const string source = @"
using System.Linq;
class TestClass
{
void TestMethod()
{
var context = new DataContext();
var sorted = context.Items.{|ST001:OrderByDescending|}(i => i.Value);
}
}
class DataContext
{
public IQueryable<Item> Items { get; set; }
}
class Item
{
public int Value { get; set; }
}";
const string fixedSource = @"
using System.Linq;
using SqrtSpace.SpaceTime.Linq;
class TestClass
{
void TestMethod()
{
var context = new DataContext();
var sorted = context.Items.OrderByDescendingExternal(i => i.Value);
}
}
class DataContext
{
public IQueryable<Item> Items { get; set; }
}
class Item
{
public int Value { get; set; }
}";
await VerifyCodeFixAsync(source, fixedSource);
}
[Fact]
public async Task GroupBy_FixesToGroupByExternal()
{
const string source = @"
using System.Linq;
class TestClass
{
void TestMethod()
{
var context = new OrderContext();
var grouped = context.Orders.{|ST001:GroupBy|}(o => o.Category);
}
}
class OrderContext
{
public IQueryable<Order> Orders { get; set; }
}
class Order
{
public string Category { get; set; }
}";
const string fixedSource = @"
using System.Linq;
using SqrtSpace.SpaceTime.Linq;
class TestClass
{
void TestMethod()
{
var context = new OrderContext();
var grouped = context.Orders.GroupByExternal(o => o.Category);
}
}
class OrderContext
{
public IQueryable<Order> Orders { get; set; }
}
class Order
{
public string Category { get; set; }
}";
await VerifyCodeFixAsync(source, fixedSource);
}
[Fact]
public async Task LargeList_FixesToAdaptiveList()
{
const string source = @"
using System.Collections.Generic;
class TestClass
{
void TestMethod()
{
var list = {|ST001:new List<string>(100000)|};
}
}";
const string fixedSource = @"
using System.Collections.Generic;
using SqrtSpace.SpaceTime.Collections;
class TestClass
{
void TestMethod()
{
var list = new AdaptiveList<string>();
}
}";
await VerifyCodeFixAsync(source, fixedSource);
}
[Fact]
public async Task ToList_InNonAsyncMethod_MakesMethodAsync()
{
const string source = @"
using System.Linq;
using System.Collections.Generic;
class TestClass
{
List<string> TestMethod()
{
var context = new TestContext();
return context.LargeCollection.{|ST001:ToList|}();
}
}
class TestContext
{
public IQueryable<string> LargeCollection { get; set; }
}";
const string fixedSource = @"
using System.Linq;
using System.Collections.Generic;
using SqrtSpace.SpaceTime.Linq;
class TestClass
{
async Task<List<string>> TestMethod()
{
var context = new TestContext();
return await context.LargeCollection.ToCheckpointedListAsync();
}
}
class TestContext
{
public IQueryable<string> LargeCollection { get; set; }
}";
await VerifyCodeFixAsync(source, fixedSource);
}
[Fact]
public async Task ComplexLinqChain_FixesMultipleOperations()
{
const string source = @"
using System.Linq;
class TestClass
{
void TestMethod()
{
var context = new BigDataContext();
var result = context.Transactions
.Where(t => t.Amount > 100)
.{|ST001:OrderBy|}(t => t.Date)
.{|ST002:GroupBy|}(t => t.Category)
.Select(g => new { Category = g.Key, Count = g.Count() })
.{|ST003:ToList|}();
}
}
class BigDataContext
{
public IQueryable<Transaction> Transactions { get; set; }
}
class Transaction
{
public DateTime Date { get; set; }
public string Category { get; set; }
public decimal Amount { get; set; }
}";
// Note: In practice, multiple code fixes would be applied separately
// This test shows the first fix (OrderBy -> OrderByExternal)
const string fixedSource = @"
using System.Linq;
using SqrtSpace.SpaceTime.Linq;
class TestClass
{
void TestMethod()
{
var context = new BigDataContext();
var result = context.Transactions
.Where(t => t.Amount > 100)
.OrderByExternal(t => t.Date)
.{|ST002:GroupBy|}(t => t.Category)
.Select(g => new { Category = g.Key, Count = g.Count() })
.{|ST003:ToList|}();
}
}
class BigDataContext
{
public IQueryable<Transaction> Transactions { get; set; }
}
class Transaction
{
public DateTime Date { get; set; }
public string Category { get; set; }
public decimal Amount { get; set; }
}";
await VerifyCodeFixAsync(source, fixedSource);
}
[Fact]
public async Task PreservesFormatting_AndComments()
{
const string source = @"
using System.Linq;
class TestClass
{
void TestMethod()
{
var context = new AppContext();
// Get all users sorted by name
var sorted = context.Users
.Where(u => u.IsActive)
.{|ST001:OrderBy|}(u => u.Name) // Sort by name
.ToList();
}
}
class AppContext
{
public IQueryable<User> Users { get; set; }
}
class User
{
public string Name { get; set; }
public bool IsActive { get; set; }
}";
const string fixedSource = @"
using System.Linq;
using SqrtSpace.SpaceTime.Linq;
class TestClass
{
void TestMethod()
{
var context = new AppContext();
// Get all users sorted by name
var sorted = context.Users
.Where(u => u.IsActive)
.OrderByExternal(u => u.Name) // Sort by name
.ToList();
}
}
class AppContext
{
public IQueryable<User> Users { get; set; }
}
class User
{
public string Name { get; set; }
public bool IsActive { get; set; }
}";
await VerifyCodeFixAsync(source, fixedSource);
}
}