Skip to content

Commit d26b36a

Browse files
Add stub for testing the precompute API. (#255)
* Add stub for testing the precompute API. Unit tests created for precompute nuget package version up to 0.1.7 * Cleanup from comments from review
1 parent f9fe443 commit d26b36a

3 files changed

Lines changed: 268 additions & 4 deletions

File tree

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using System.Text;
5+
using System.Threading;
6+
using System.Threading.Tasks;
7+
using NUnit.Framework;
8+
9+
namespace ElectionGuard.Encryption.Tests
10+
{
11+
[TestFixture]
12+
class TestPrecompute
13+
{
14+
[Test]
15+
public void Test_Precompute_Status_NoStarted()
16+
{
17+
Precompute precompute = new Precompute();
18+
19+
var status = precompute.GetStatus();
20+
21+
Assert.AreEqual(PrecomputeState.NotStarted, status.CurrentState);
22+
}
23+
24+
[Test]
25+
public void Test_Precompute_Status_Running()
26+
{
27+
Precompute precompute = new Precompute();
28+
29+
CancellationTokenSource cts = new CancellationTokenSource();
30+
31+
precompute.StartPrecomputeAsync(1, cts.Token);
32+
var status = precompute.GetStatus();
33+
precompute.StopPrecompute();
34+
35+
Assert.AreEqual(PrecomputeState.Running, status.CurrentState);
36+
}
37+
38+
[Test]
39+
public void Test_Precompute_Status_Stopped()
40+
{
41+
Precompute precompute = new Precompute();
42+
43+
CancellationTokenSource cts = new CancellationTokenSource();
44+
45+
precompute.StartPrecomputeAsync(1, cts.Token);
46+
precompute.StopPrecompute();
47+
Thread.Sleep(1000);
48+
49+
var status = precompute.GetStatus();
50+
51+
Assert.AreEqual(PrecomputeState.UserStopped, status.CurrentState);
52+
}
53+
54+
}
55+
}

bindings/netstandard/ElectionGuard/ElectionGuard.Encryption/ElectionGuard.Encryption.csproj

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,9 @@
77
<!-- Project -->
88
<RootNamespace>ElectionGuard</RootNamespace>
99
<AssemblyName>ElectionGuard.Encryption</AssemblyName>
10-
<Version>0.1.6</Version>
11-
<AssemblyVersion>0.1.6.0</AssemblyVersion>
12-
<AssemblyFileVersion>0.1.6.0</AssemblyFileVersion>
10+
<Version>0.1.7</Version>
11+
<AssemblyVersion>0.1.7.0</AssemblyVersion>
12+
<AssemblyFileVersion>0.1.7.0</AssemblyFileVersion>
1313
</PropertyGroup>
1414

1515
<PropertyGroup>
@@ -19,7 +19,7 @@
1919
<Title>ElectionGuard Encryption</Title>
2020
<Description>Open source implementation of ElectionGuard's ballot encryption.</Description>
2121
<Authors>Microsoft</Authors>
22-
<PackageVersion>0.1.6</PackageVersion>
22+
<PackageVersion>0.1.7</PackageVersion>
2323
<PackageLicenseExpression>MIT</PackageLicenseExpression>
2424
<PackageProjectUrl>https://github.com/microsoft/electionguard-cpp</PackageProjectUrl>
2525
<RepositoryUrl>https://github.com/microsoft/electionguard-cpp</RepositoryUrl>
Lines changed: 209 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,209 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Text;
4+
using System.Threading;
5+
using System.Threading.Tasks;
6+
7+
namespace ElectionGuard
8+
{
9+
/// <summary>
10+
/// States that the precompute process can be in.
11+
/// </summary>
12+
public enum PrecomputeState
13+
{
14+
/// <summary>
15+
/// The precompute has not been started.
16+
/// </summary>
17+
NotStarted = 0,
18+
/// <summary>
19+
/// The precompute is currently running
20+
/// </summary>
21+
Running = 1,
22+
/// <summary>
23+
/// The user stopped the precompute
24+
/// </summary>
25+
UserStopped = 2,
26+
/// <summary>
27+
/// The precompute finished
28+
/// </summary>
29+
Completed = 3,
30+
}
31+
32+
/// <summary>
33+
/// Status for the precompute process
34+
/// </summary>
35+
public struct PrecomputeStatus
36+
{
37+
/// <summary>
38+
/// Percentage of the calculations that are complete
39+
/// </summary>
40+
public double Percentage;
41+
42+
/// <summary>
43+
/// The number of exponentiations that are completed
44+
/// </summary>
45+
public long CompletedExponentiationsCount;
46+
47+
/// <summary>
48+
/// Current status of the precompute process
49+
/// </summary>
50+
public PrecomputeState CurrentState;
51+
}
52+
53+
/// <summary>
54+
/// Delegate definition to return back the status of the precompute process
55+
/// </summary>
56+
/// <returns><see cref="PrecomputeStatus">PrecomputeStatus</see> with all of the latest information</returns>
57+
public delegate void StatusEventHandler(PrecomputeStatus status);
58+
59+
/// <summary>
60+
/// Interface for the precompute API to start and stop the precompute calculations
61+
/// </summary>
62+
public interface IPrecomputeAPI
63+
{
64+
/// <summary>
65+
/// Starts the precompute process by creating a new thread to run the process
66+
/// </summary>
67+
/// <param name="maxexp">The max exponentiation to be calculated</param>
68+
/// <param name="token">CancelationToken that can be used to start the process</param>
69+
/// <returns></returns>
70+
void StartPrecomputeAsync(long maxexp, CancellationToken token);
71+
72+
/// <summary>
73+
/// Stops the precompute process
74+
/// </summary>
75+
void StopPrecompute();
76+
77+
/// <summary>
78+
/// Get the current status for the current running process
79+
/// </summary>
80+
/// <returns><see cref="PrecomputeStatus">PrecomputeStatus</see> with all of the latest information</returns>
81+
PrecomputeStatus GetStatus();
82+
83+
/// <summary>
84+
/// Event handler that will give back progress to the calling code
85+
/// </summary>
86+
event StatusEventHandler ProgressEvent;
87+
88+
/// <summary>
89+
/// Event handler that will signal that the entire precompute is completed
90+
/// </summary>
91+
event StatusEventHandler CompletedEvent;
92+
}
93+
94+
/// <summary>
95+
/// Class that controls the precompute process
96+
/// </summary>
97+
public class Precompute : IPrecomputeAPI
98+
{
99+
private CancellationTokenSource cancelTokenSource;
100+
private CancellationToken cancelToken;
101+
private PrecomputeStatus currentStatus = new PrecomputeStatus
102+
{
103+
Percentage = 0,
104+
CompletedExponentiationsCount = 0,
105+
CurrentState = PrecomputeState.NotStarted
106+
};
107+
private Thread workerThread;
108+
private long delay = 2;
109+
110+
/// <summary>
111+
/// Event handler that will give back progress to the calling code
112+
/// </summary>
113+
public event StatusEventHandler ProgressEvent;
114+
115+
/// <summary>
116+
/// Event handler that will signal that the entire precompute is completed
117+
/// </summary>
118+
public event StatusEventHandler CompletedEvent;
119+
120+
/// <summary>
121+
/// Internal method used to call the completed event
122+
/// </summary>
123+
private void OnCompletedEvent()
124+
{
125+
CompletedEvent?.Invoke(currentStatus);
126+
}
127+
128+
/// <summary>
129+
/// Internal method used to call the progress event
130+
/// </summary>
131+
private void OnProgressEvent()
132+
{
133+
ProgressEvent?.Invoke(currentStatus);
134+
}
135+
136+
/// <summary>
137+
/// Get the current status for the current running process
138+
/// </summary>
139+
/// <returns><see cref="PrecomputeStatus">PrecomputeStatus</see> with all of the latest information</returns>
140+
public PrecomputeStatus GetStatus()
141+
{
142+
return currentStatus;
143+
}
144+
145+
/// <summary>
146+
/// Starts the precompute process by creating a new thread to run the process
147+
/// </summary>
148+
/// <param name="maxexp">The max exponentiation to be calculated</param>
149+
/// <param name="token">CancelationToken that can be used to start the process</param>
150+
public void StartPrecomputeAsync(long maxexp, CancellationToken token)
151+
{
152+
cancelTokenSource = CancellationTokenSource.CreateLinkedTokenSource(cancelToken);
153+
cancelToken = token;
154+
currentStatus.CurrentState = PrecomputeState.Running;
155+
delay = maxexp;
156+
workerThread = new Thread(WorkerMethod);
157+
workerThread.Start();
158+
}
159+
160+
/// <summary>
161+
/// Stops the precompute process
162+
/// </summary>
163+
public void StopPrecompute()
164+
{
165+
if (currentStatus.CurrentState == PrecomputeState.Running)
166+
{
167+
currentStatus.CurrentState = PrecomputeState.UserStopped;
168+
cancelTokenSource?.Cancel();
169+
}
170+
}
171+
172+
/// <summary>
173+
/// Dummy method to be used for the stubbing out until the exponentiation code is complete
174+
/// </summary>
175+
private void WorkerMethod()
176+
{
177+
double progress = 0;
178+
if (cancelTokenSource == null)
179+
{
180+
cancelTokenSource = new CancellationTokenSource();
181+
}
182+
while (!cancelToken.IsCancellationRequested)
183+
{
184+
Thread.Sleep((int)delay * 1000);
185+
186+
if (cancelToken.IsCancellationRequested)
187+
{
188+
currentStatus.CurrentState = PrecomputeState.UserStopped;
189+
OnCompletedEvent();
190+
return;
191+
}
192+
193+
progress += 10;
194+
currentStatus.Percentage = progress;
195+
if (progress == 100)
196+
{
197+
currentStatus.CurrentState = PrecomputeState.Completed;
198+
OnCompletedEvent();
199+
return;
200+
}
201+
else
202+
{
203+
OnProgressEvent();
204+
}
205+
}
206+
}
207+
208+
}
209+
}

0 commit comments

Comments
 (0)