Skip to content

Commit

Permalink
Merge pull request #26 from davewalker5/BSR-46-Fix-Failing-Tests
Browse files Browse the repository at this point in the history
Add expression builder ; Fix failing unit tests
  • Loading branch information
davewalker5 committed Sep 6, 2023
2 parents d876364 + e7b6eab commit 3548703
Show file tree
Hide file tree
Showing 5 changed files with 150 additions and 20 deletions.
9 changes: 9 additions & 0 deletions src/BaseStationReader.Entities/Expressions/TrackerFilter.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
namespace BaseStationReader.Entities.Expressions
{
public class TrackerFilter
{
public string PropertyName { get; set; } = "";
public TrackerFilterOperator Operator { get; set; }
public object? Value { get; set; } = null;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
namespace BaseStationReader.Entities.Expressions
{
public enum TrackerFilterOperator
{
Equals,
NotEquals,
GreaterThan,
GreaterThanOrEqual,
LessThan,
LessThanOrEqual
}
}
14 changes: 14 additions & 0 deletions src/BaseStationReader.Entities/Interfaces/IExpressionBuilder.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
using BaseStationReader.Entities.Expressions;
using System.Linq.Expressions;

namespace BaseStationReader.Entities.Interfaces
{
public interface IExpressionBuilder<T> where T : class
{
IList<TrackerFilter> Filters { get; set; }

void Add(string propertyName, TrackerFilterOperator @operator, object? value);
Expression<Func<T, bool>>? Build();
void Clear();
}
}
93 changes: 93 additions & 0 deletions src/BaseStationReader.Logic/Database/ExpressionBuilder.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
using BaseStationReader.Entities.Expressions;
using BaseStationReader.Entities.Interfaces;
using System.Linq.Expressions;

namespace BaseStationReader.Logic.Database
{
public class ExpressionBuilder<T> : IExpressionBuilder<T> where T : class
{
public IList<TrackerFilter> Filters { get; set; } = new List<TrackerFilter>();

/// <summary>
/// Clear the current filters
/// </summary>
public void Clear()
{
Filters.Clear();
}

/// <summary>
/// Add a clause to the current filters
/// </summary>
/// <param name="propertyName"></param>
/// <param name="operator"></param>
/// <param name="value"></param>
public void Add(string propertyName, TrackerFilterOperator @operator, object? value)
{
Filters.Add(new TrackerFilter
{
PropertyName = propertyName,
Operator = @operator,
Value = value
});
}

/// <summary>
/// Build a lambda expression from the current filters
/// </summary>
/// <returns></returns>
/// <exception cref="NotImplementedException"></exception>
public Expression<Func<T, bool>>? Build()
{
// If there are no filters, return null
if (Filters.Count == 0)
{
return null;
}

// Get an expression representing the object type
var parameter = Expression.Parameter(typeof(T), "p");

Expression? body = null;
foreach (var filter in Filters)
{
// Get an expression representing the class member for this filter and a constant representing
// the value
var member = Expression.Property(parameter, filter.PropertyName);
var constant = Expression.Constant(filter.Value);

// Construct the body of this clause
Expression expression;
switch (filter.Operator)
{
case TrackerFilterOperator.Equals:
expression = Expression.Equal(member, constant);
break;
case TrackerFilterOperator.NotEquals:
expression = Expression.NotEqual(member, constant);
break;
case TrackerFilterOperator.GreaterThan:
expression = Expression.GreaterThan(member, constant);
break;
case TrackerFilterOperator.GreaterThanOrEqual:
expression = Expression.GreaterThanOrEqual(member, constant);
break;
case TrackerFilterOperator.LessThan:
expression = Expression.LessThan(member, constant);
break;
case TrackerFilterOperator.LessThanOrEqual:
expression = Expression.LessThanOrEqual(member, constant);
break;
default:
throw new NotImplementedException();
}

// Add this clause to the body of the overall expression
body = (body == null) ? expression : Expression.AndAlso(body, expression);
}

// Construct and return the lambda expression
return Expression.Lambda<Func<T, bool>>(body!, parameter);
}
}
}
42 changes: 22 additions & 20 deletions src/BaseStationReader.Tests/QueuedWriterTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ public void TestCleanup()
}

[TestMethod]
public async Task AddNewAircraftTest()
public void AddNewAircraftTest()
{
Push(new Aircraft
{
Expand All @@ -74,20 +74,20 @@ public async Task AddNewAircraftTest()

WaitForQueueToEmpty();

var aircraft = await _aircraftWriter!.GetAsync(x => x.Address == Address);
var aircraft = Task.Run(() => _aircraftWriter!.GetAsync(x => x.Address == Address)).Result;
Assert.IsNotNull(aircraft);
Assert.AreEqual(Address, aircraft.Address);
}

[TestMethod]
public async Task UpdateExistingAircraftTest()
public void UpdateExistingAircraftTest()
{
var added = await _aircraftWriter!.WriteAsync(new Aircraft
var added = Task.Run(() => _aircraftWriter!.WriteAsync(new Aircraft
{
Address = Address,
FirstSeen = DateTime.Now.AddMinutes(-10),
LastSeen = DateTime.Now
});
})).Result;

Push(new Aircraft
{
Expand All @@ -106,7 +106,7 @@ public async Task UpdateExistingAircraftTest()

WaitForQueueToEmpty();

var aircraft = await _aircraftWriter.ListAsync(x => x.Address == Address);
var aircraft = Task.Run(() => _aircraftWriter!.ListAsync(x => x.Address == Address)).Result;
Assert.IsNotNull(aircraft);
Assert.AreEqual(1, aircraft.Count);
Assert.AreEqual(added.Id, aircraft[0].Id);
Expand All @@ -123,14 +123,14 @@ public async Task UpdateExistingAircraftTest()
}

[TestMethod]
public async Task AddActivePositionTest()
public void AddActivePositionTest()
{
var aircraft = await _aircraftWriter!.WriteAsync(new Aircraft
var aircraft = Task.Run(() => _aircraftWriter!.WriteAsync(new Aircraft
{
Address = Address,
FirstSeen = DateTime.Now.AddMinutes(-10),
LastSeen = DateTime.Now
});
})).Result;

Push(new AircraftPosition
{
Expand All @@ -143,7 +143,7 @@ public async Task AddActivePositionTest()

WaitForQueueToEmpty();

var position = await _positionWriter!.GetAsync(x => x.AircraftId == aircraft.Id);
var position = Task.Run(() => _positionWriter!.GetAsync(x => x.AircraftId == aircraft.Id)).Result;
Assert.IsNotNull(position);
Assert.IsTrue(position.Id > 0);
Assert.AreEqual(aircraft.Id, position.AircraftId);
Expand All @@ -153,16 +153,16 @@ public async Task AddActivePositionTest()
}

[TestMethod]
public async Task StaleRecordIsLockedOnUpdateTest()
public void StaleRecordIsLockedOnUpdateTest()
{
await _aircraftWriter!.WriteAsync(new Aircraft
Task.Run(() => _aircraftWriter!.WriteAsync(new Aircraft
{
Address = Address,
FirstSeen = DateTime.Now.AddMinutes(-20),
LastSeen = DateTime.Now.AddMinutes(-15)
});
})).Wait();

var added = await _aircraftWriter.GetAsync(x => x.Address == Address);
var added = Task.Run(() => _aircraftWriter!.GetAsync(x => x.Address == Address)).Result;
Assert.IsNotNull(added);
Assert.IsTrue(added.Id > 0);
Assert.IsFalse(added.Locked);
Expand All @@ -184,7 +184,7 @@ public async Task StaleRecordIsLockedOnUpdateTest()

WaitForQueueToEmpty();

var aircraft = await _aircraftWriter.ListAsync(x => true);
var aircraft = Task.Run(() => _aircraftWriter!.ListAsync(x => true)).Result;
Assert.IsNotNull(aircraft);
Assert.AreEqual(2, aircraft.Count);
Assert.IsTrue(aircraft[0].Id > 0);
Expand All @@ -193,16 +193,16 @@ public async Task StaleRecordIsLockedOnUpdateTest()
}

[TestMethod]
public async Task NewSessionLocksAllTest()
public void NewSessionLocksAllTest()
{
await _aircraftWriter!.WriteAsync(new Aircraft
Task.Run(() => _aircraftWriter!.WriteAsync(new Aircraft
{
Address = Address,
FirstSeen = DateTime.Now.AddMinutes(-10),
LastSeen = DateTime.Now
});
})).Wait();

var aircraft = await _aircraftWriter.GetAsync(x => x.Address == Address);
var aircraft = Task.Run(() => _aircraftWriter!.GetAsync(x => x.Address == Address)).Result;
Assert.IsNotNull(aircraft);
Assert.IsTrue(aircraft.Id > 0);
Assert.IsFalse(aircraft.Locked);
Expand All @@ -211,7 +211,7 @@ public async Task NewSessionLocksAllTest()
_writer.Start();
WaitForQueueToEmpty();

var locked = await _aircraftWriter.GetAsync(x => x.Address == Address);
var locked = Task.Run(() => _aircraftWriter!.GetAsync(x => x.Address == Address)).Result;
Assert.IsNotNull(locked);
Assert.AreEqual(aircraft.Id, locked.Id);
Assert.IsTrue(locked.Locked);
Expand Down Expand Up @@ -245,6 +245,8 @@ private void WaitForQueueToEmpty()
{
}
stopwatch.Stop();

Assert.IsTrue(stopwatch.ElapsedMilliseconds <= MaximumWriterWaitTimeMs);
}

/// <summary>
Expand Down

0 comments on commit 3548703

Please sign in to comment.