Skip to content

Commit

Permalink
Add more tests (#9)
Browse files Browse the repository at this point in the history
* Add more tests

* Fix config

* Test (#8)

* Try and get it on master?

* Add readme badge

* Fix config

* Test solid side

* Add build status

* Wrap filesystem operations

* Remove service option

* Remove --service from service

* Only delete the pid file if contents match current pid

* Don't try to read a non-existent file

* Add tests for special file

* Don't check for overflows now

* Start IoC container with file access

* Make a move to reactive updates instead of timed ones

* Only do reactive render

* Allow specifying fps

* Make sure we always render the first frame

* Make a faster file implementation

* Use exponential average

* Update the readme
  • Loading branch information
withinboredom authored Nov 26, 2019
1 parent 4c5ee31 commit c759cc6
Show file tree
Hide file tree
Showing 38 changed files with 951 additions and 334 deletions.
18 changes: 16 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

[![Coverage Status](https://coveralls.io/repos/github/withinboredom/system-76-keyboards/badge.svg?branch=fix/codecov)](https://coveralls.io/github/withinboredom/system-76-keyboards?branch=fix/codecov)

![Build Status](https://github.com/withinboredom/system-76-keyboards/workflows/Builder/badge.svg)

Create a floating rainbow effect that moves across your keyboard!

# Installation
Expand All @@ -15,8 +17,20 @@ Create a floating rainbow effect that moves across your keyboard!

## Changing modes

- `keyboard-color rainbow --install`
- or `echo yy | keyboard-color monitor --install` for a non-interactive experience
- `keyboard-color rainbow`: Show a pretty rainbow that moves across the keyboard
- `keyboard-color monitor`: Show cpu usage
- `keyboard-color solidcolor --color FFAAFF`: Set the color to whatever hex color you want

## Filters

- `keyboard-color MODE --filter WashedOut`: Get a washed out look
- `keyboard-color MODE --filter BlackWhite`: A terrible attempt at black and white
- `keyboard-color MODE --filter Hearbeat`: Dim and brighten the keyboard based on cpu usage

## Setting FPS

The default is 10 frames per second, but you may find that it causes considerable CPU usage on your machine (it's about
5% on my machine with `monitor` mode), you can change it with the `--fps` option.

## Colors for `monitor`

Expand Down
12 changes: 12 additions & 0 deletions csharp/UnitTests/ColorSpace/HsbTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -36,5 +36,17 @@ public void CanConvertRgb()
var c1 = new Hsb(new Rgb(38, 33, 33));
Assert.AreEqual(c1, new Hsb(0, 0.13157894D, 0.14901960D));
}

[Test]
public void SetsWork()
{
var color = new Hsb(100, 1, 1);
var nohue = new Hsb(0, 1, 1);
var nosat = new Hsb(100, 0, 1);
var nobri = new Hsb(100, 1, 0);
Assert.AreEqual(nohue, color.SetHue(0));
Assert.AreEqual(nosat, color.SetSaturation(0));
Assert.AreEqual(nobri, color.SetBrightness(0));
}
}
}
16 changes: 16 additions & 0 deletions csharp/UnitTests/FakeContainer.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
using System.Collections.Generic;
using keyboards;
using keyboards.Monitors;

namespace UnitTests
{
public class FakeContainer : IControlContainer
{
public HashSet<IMonitor> Monitors { get; set; }

public IFile File(string filename)
{
return new FakeFile(filename);
}
}
}
40 changes: 40 additions & 0 deletions csharp/UnitTests/FakeFile.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
using System.Threading.Tasks;
using keyboards;

namespace UnitTests
{
public class FakeFile : IFile
{
public FakeFile(string filename)
{
}

public bool Exists { get; internal set; }

public bool HasPermission { get; internal set; }

public string Contents { get; internal set; }

public Task Commit(string contents)
{
Contents = contents;
return Task.CompletedTask;
}

public Task<string> Read()
{
return Task.FromResult(Contents);
}

public Task<string[]> Lines()
{
return Task.FromResult(Contents.Split('\n'));
}

public void Delete()
{
Exists = false;
Contents = string.Empty;
}
}
}
34 changes: 34 additions & 0 deletions csharp/UnitTests/Sides/SolidTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
using System.Threading.Tasks;
using keyboards;
using keyboards.ColorSpace;
using keyboards.Filters;
using keyboards.Sides;
using NUnit.Framework;

namespace UnitTests.Sides
{
public class SolidTests
{
private readonly IFile _fixtureFile = new FakeFile("test-color");

[SetUp]
public async Task CreateFixture()
{
await _fixtureFile.Commit("FF00FF");
}

[TearDown]
public void ResetFixture()
{
_fixtureFile.Delete();
}

[Test]
public void TestSolidColor()
{
var side = new Solid(Rgb.FromHex("FFFFFF")) {Led = _fixtureFile};
side.Commit(new IFilter[] { });
Assert.AreEqual("FFFFFF", side.Led.Contents);
}
}
}
102 changes: 102 additions & 0 deletions csharp/UnitTests/SpecialFileTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
using System.IO;
using System.Threading.Tasks;
using keyboards;
using NUnit.Framework;

namespace UnitTests
{
public class SpecialFileTests
{
private const string NoExistsPath = "noexists";
private static string ExistsPath => Path.GetTempFileName();

private static string NoPermsPath
{
get
{
var path = Path.GetTempFileName();
File.SetAttributes(path, FileAttributes.ReadOnly);
return path;
}
}

[Test]
public void CanCheckExists()
{
var exists = new SpecialFile(ExistsPath);
var noExists = new SpecialFile(NoExistsPath);

Assert.IsTrue(exists.Exists);
Assert.IsFalse(noExists.Exists);
}

[Test]
public void HasWritePermissionsWithWritableFile()
{
var canWrite = new SpecialFile(ExistsPath);

Assert.IsTrue(canWrite.HasPermission);
}

[Test]
public void NoPermissionsWithReadOnlyFile()
{
var noWrite = new SpecialFile(NoPermsPath);
Assert.IsFalse(noWrite.HasPermission);
}

[Test]
public void PermissionsToNonExistingFile()
{
var noExists = new SpecialFile(NoExistsPath);
Assert.IsTrue(noExists.HasPermission);
}

[Test]
public async Task CanWriteToRegularFile()
{
var exists = new SpecialFile(Path.GetTempFileName());
await exists.Commit("test");
Assert.AreEqual("test", await exists.Read());
Assert.AreEqual("test", exists.Contents);
Assert.AreEqual("test", (await exists.Lines())[0]);
}

[Test]
public async Task CannotWriteToUnwritableFile()
{
var no = new SpecialFile(NoPermsPath);
await no.Commit("test");
Assert.AreEqual("", no.Contents);
}

[Test]
public void CanDeleteNonExistentFile()
{
Assert.IsFalse(File.Exists(NoExistsPath));
var no = new SpecialFile(NoExistsPath);
no.Delete();
Assert.DoesNotThrow(() => no.Delete());
}

[Test]
public void CanDeleteRegularFile()
{
var path = ExistsPath;
Assert.IsTrue(File.Exists(path));
var file = new SpecialFile(path);
Assert.DoesNotThrow(() => file.Delete());
Assert.IsFalse(File.Exists(path));
}

[Test]
public void CanDeleteReadOnlyFile()
{
var path = NoPermsPath;
Assert.IsTrue(File.Exists(path));
var file = new SpecialFile(path);
Assert.DoesNotThrow(() => file.Delete());
Assert.IsTrue(File.Exists(path));
}
}
}
1 change: 0 additions & 1 deletion csharp/UnitTests/UnitTests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

<PropertyGroup>
<TargetFramework>netcoreapp3.0</TargetFramework>

<IsPackable>false</IsPackable>
</PropertyGroup>

Expand Down
15 changes: 15 additions & 0 deletions csharp/keyboards/ControlContainer.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
using System.Collections.Generic;
using keyboards.Monitors;

namespace keyboards
{
public class ControlContainer : IControlContainer
{
public IFile File(string filename)
{
return new FastFile(filename);
}

public HashSet<IMonitor> Monitors { get; set; } = new HashSet<IMonitor>();
}
}
43 changes: 43 additions & 0 deletions csharp/keyboards/FastFile.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
using System.IO;

namespace keyboards
{
/// <summary>
/// A file implementation that assumes the world won't change
/// </summary>
public class FastFile : SpecialFile
{
private bool? _existsCache;
private bool? _hasPermissionsCache;

public new bool Exists
{
get
{
if (_existsCache == null)
{
_existsCache = base.Exists;
}

return _existsCache.Value;
}
}

public new bool HasPermission
{
get
{
if (_hasPermissionsCache == null)
{
_hasPermissionsCache = base.HasPermission;
}

return _hasPermissionsCache.Value;
}
}

public FastFile(string filename) : base(filename)
{
}
}
}
29 changes: 19 additions & 10 deletions csharp/keyboards/Filters/HeartFilter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,7 @@ public class HeartFilter : IFilter
/// <summary>
/// Keep a moving average
/// </summary>
private readonly MovingAverage _average;

/// <summary>
/// The monitor to use
/// </summary>
private readonly IMonitor _monitor;
private readonly MovingAverage _average = new MovingAverage();

/// <summary>
/// The precalculated steps
Expand Down Expand Up @@ -75,11 +70,10 @@ public class HeartFilter : IFilter
/// <summary>
/// Initialize the filter
/// </summary>
public HeartFilter()
public HeartFilter(IControlContainer container)
{
_lastUpdate = DateTime.Now;
_monitor = new Cpu();
_average = new MovingAverage(40);
Cpu.Instance(container).Changed += OnChanged;

var steps = new List<double>();
var theta = 0D;
Expand All @@ -102,14 +96,19 @@ public HeartFilter()
_currentStep = 0;
}

/// <summary>
/// The latest value from the sensor
/// </summary>
private double Value { get; set; }

/// <summary>
/// Called after render but before filtering, exactly once
/// </summary>
/// <param name="time">The time of the render</param>
/// <returns></returns>
public Task PreApply(long time)
{
_lastMeasure = _average.GetAverage(_monitor.Percentage) / 100D;
_lastMeasure = _average.GetAverage(Value) / 100D;
_currentUpdate = DateTime.Now;

_lastMeasure = _lastMeasure >= 1 ? .99D : _lastMeasure;
Expand Down Expand Up @@ -141,5 +140,15 @@ public Task<Rgb> ApplyFilter(Rgb color)

return Task.FromResult(next);
}

/// <summary>
/// Called when the sensor updates
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void OnChanged(object? sender, double e)
{
Value = e;
}
}
}
Loading

0 comments on commit c759cc6

Please sign in to comment.