mirror of
https://github.com/vacp2p/cs-codex-dist-tests.git
synced 2025-02-23 15:58:21 +00:00
Makes timings not static and ties them to test lifecycle
This commit is contained in:
parent
2ed6993b58
commit
5a4a5795b2
@ -6,10 +6,12 @@ namespace DistTestCore.Codex
|
|||||||
public class CodexAccess
|
public class CodexAccess
|
||||||
{
|
{
|
||||||
private readonly BaseLog log;
|
private readonly BaseLog log;
|
||||||
|
private readonly ITimeSet timeSet;
|
||||||
|
|
||||||
public CodexAccess(BaseLog log, RunningContainer runningContainer)
|
public CodexAccess(BaseLog log, ITimeSet timeSet, RunningContainer runningContainer)
|
||||||
{
|
{
|
||||||
this.log = log;
|
this.log = log;
|
||||||
|
this.timeSet = timeSet;
|
||||||
Container = runningContainer;
|
Container = runningContainer;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -44,7 +46,7 @@ namespace DistTestCore.Codex
|
|||||||
{
|
{
|
||||||
var ip = Container.Pod.Cluster.IP;
|
var ip = Container.Pod.Cluster.IP;
|
||||||
var port = Container.ServicePorts[0].Number;
|
var port = Container.ServicePorts[0].Number;
|
||||||
return new Http(log, ip, port, baseUrl: "/api/codex/v1");
|
return new Http(log, timeSet, ip, port, baseUrl: "/api/codex/v1");
|
||||||
}
|
}
|
||||||
|
|
||||||
public string ConnectToPeer(string peerId, string peerMultiAddress)
|
public string ConnectToPeer(string peerId, string peerMultiAddress)
|
||||||
|
@ -64,7 +64,7 @@ namespace DistTestCore
|
|||||||
|
|
||||||
private OnlineCodexNode CreateOnlineCodexNode(RunningContainer c, ICodexNodeFactory factory)
|
private OnlineCodexNode CreateOnlineCodexNode(RunningContainer c, ICodexNodeFactory factory)
|
||||||
{
|
{
|
||||||
var access = new CodexAccess(lifecycle.Log, c);
|
var access = new CodexAccess(lifecycle.Log, lifecycle.TimeSet, c);
|
||||||
EnsureOnline(access);
|
EnsureOnline(access);
|
||||||
return factory.CreateOnlineCodexNode(access, this);
|
return factory.CreateOnlineCodexNode(access, this);
|
||||||
}
|
}
|
||||||
|
@ -4,13 +4,13 @@ namespace DistTestCore
|
|||||||
{
|
{
|
||||||
public class Configuration
|
public class Configuration
|
||||||
{
|
{
|
||||||
public KubernetesWorkflow.Configuration GetK8sConfiguration()
|
public KubernetesWorkflow.Configuration GetK8sConfiguration(ITimeSet timeSet)
|
||||||
{
|
{
|
||||||
return new KubernetesWorkflow.Configuration(
|
return new KubernetesWorkflow.Configuration(
|
||||||
k8sNamespacePrefix: "ct-",
|
k8sNamespacePrefix: "ct-",
|
||||||
kubeConfigFile: null,
|
kubeConfigFile: null,
|
||||||
operationTimeout: Timing.K8sOperationTimeout(),
|
operationTimeout: timeSet.K8sOperationTimeout(),
|
||||||
retryDelay: Timing.K8sServiceDelay(),
|
retryDelay: timeSet.WaitForK8sServiceDelay(),
|
||||||
locationMap: new[]
|
locationMap: new[]
|
||||||
{
|
{
|
||||||
new ConfigurationLocationEntry(Location.BensOldGamingMachine, "worker01"),
|
new ConfigurationLocationEntry(Location.BensOldGamingMachine, "worker01"),
|
||||||
|
@ -32,13 +32,11 @@ namespace DistTestCore
|
|||||||
{
|
{
|
||||||
// Previous test run may have been interrupted.
|
// Previous test run may have been interrupted.
|
||||||
// Begin by cleaning everything up.
|
// Begin by cleaning everything up.
|
||||||
Timing.UseLongTimeouts = false;
|
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
Stopwatch.Measure(fixtureLog, "Global setup", () =>
|
Stopwatch.Measure(fixtureLog, "Global setup", () =>
|
||||||
{
|
{
|
||||||
var wc = new WorkflowCreator(fixtureLog, configuration.GetK8sConfiguration());
|
var wc = new WorkflowCreator(fixtureLog, configuration.GetK8sConfiguration(GetTimeSet()));
|
||||||
wc.CreateWorkflow().DeleteAllResources();
|
wc.CreateWorkflow().DeleteAllResources();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -58,8 +56,6 @@ namespace DistTestCore
|
|||||||
[SetUp]
|
[SetUp]
|
||||||
public void SetUpDistTest()
|
public void SetUpDistTest()
|
||||||
{
|
{
|
||||||
Timing.UseLongTimeouts = ShouldUseLongTimeouts();
|
|
||||||
|
|
||||||
if (GlobalTestFailure.HasFailed)
|
if (GlobalTestFailure.HasFailed)
|
||||||
{
|
{
|
||||||
Assert.Inconclusive("Skip test: Previous test failed during clean up.");
|
Assert.Inconclusive("Skip test: Previous test failed during clean up.");
|
||||||
@ -145,21 +141,6 @@ namespace DistTestCore
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool ShouldUseLongTimeouts()
|
|
||||||
{
|
|
||||||
// Don't be fooled! TestContext.CurrentTest.Test allows you easy access to the attributes of the current test.
|
|
||||||
// But this doesn't work for tests making use of [TestCase]. So instead, we use reflection here to figure out
|
|
||||||
// if the attribute is present.
|
|
||||||
var currentTest = TestContext.CurrentContext.Test;
|
|
||||||
var className = currentTest.ClassName;
|
|
||||||
var methodName = currentTest.MethodName;
|
|
||||||
|
|
||||||
var testClasses = testAssemblies.SelectMany(a => a.GetTypes()).Where(c => c.FullName == className).ToArray();
|
|
||||||
var testMethods = testClasses.SelectMany(c => c.GetMethods()).Where(m => m.Name == methodName).ToArray();
|
|
||||||
|
|
||||||
return testMethods.Any(m => m.GetCustomAttribute<UseLongTimeoutsAttribute>() != null);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void CreateNewTestLifecycle()
|
private void CreateNewTestLifecycle()
|
||||||
{
|
{
|
||||||
var testName = GetCurrentTestName();
|
var testName = GetCurrentTestName();
|
||||||
@ -167,7 +148,7 @@ namespace DistTestCore
|
|||||||
{
|
{
|
||||||
lock (lifecycleLock)
|
lock (lifecycleLock)
|
||||||
{
|
{
|
||||||
lifecycles.Add(testName, new TestLifecycle(fixtureLog.CreateTestLog(), configuration));
|
lifecycles.Add(testName, new TestLifecycle(fixtureLog.CreateTestLog(), configuration, GetTimeSet()));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -185,6 +166,27 @@ namespace DistTestCore
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private ITimeSet GetTimeSet()
|
||||||
|
{
|
||||||
|
if (ShouldUseLongTimeouts()) return new LongTimeSet();
|
||||||
|
return new DefaultTimeSet();
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool ShouldUseLongTimeouts()
|
||||||
|
{
|
||||||
|
// Don't be fooled! TestContext.CurrentTest.Test allows you easy access to the attributes of the current test.
|
||||||
|
// But this doesn't work for tests making use of [TestCase]. So instead, we use reflection here to figure out
|
||||||
|
// if the attribute is present.
|
||||||
|
var currentTest = TestContext.CurrentContext.Test;
|
||||||
|
var className = currentTest.ClassName;
|
||||||
|
var methodName = currentTest.MethodName;
|
||||||
|
|
||||||
|
var testClasses = testAssemblies.SelectMany(a => a.GetTypes()).Where(c => c.FullName == className).ToArray();
|
||||||
|
var testMethods = testClasses.SelectMany(c => c.GetMethods()).Where(m => m.Name == methodName).ToArray();
|
||||||
|
|
||||||
|
return testMethods.Any(m => m.GetCustomAttribute<UseLongTimeoutsAttribute>() != null);
|
||||||
|
}
|
||||||
|
|
||||||
private void IncludeLogsAndMetricsOnTestFailure(TestLifecycle lifecycle)
|
private void IncludeLogsAndMetricsOnTestFailure(TestLifecycle lifecycle)
|
||||||
{
|
{
|
||||||
var result = TestContext.CurrentContext.Result;
|
var result = TestContext.CurrentContext.Result;
|
||||||
|
@ -10,13 +10,15 @@ namespace DistTestCore
|
|||||||
public class Http
|
public class Http
|
||||||
{
|
{
|
||||||
private readonly BaseLog log;
|
private readonly BaseLog log;
|
||||||
|
private readonly ITimeSet timeSet;
|
||||||
private readonly string ip;
|
private readonly string ip;
|
||||||
private readonly int port;
|
private readonly int port;
|
||||||
private readonly string baseUrl;
|
private readonly string baseUrl;
|
||||||
|
|
||||||
public Http(BaseLog log, string ip, int port, string baseUrl)
|
public Http(BaseLog log, ITimeSet timeSet, string ip, int port, string baseUrl)
|
||||||
{
|
{
|
||||||
this.log = log;
|
this.log = log;
|
||||||
|
this.timeSet = timeSet;
|
||||||
this.ip = ip;
|
this.ip = ip;
|
||||||
this.port = port;
|
this.port = port;
|
||||||
this.baseUrl = baseUrl;
|
this.baseUrl = baseUrl;
|
||||||
@ -103,7 +105,7 @@ namespace DistTestCore
|
|||||||
log.Debug($"({url}) = '{message}'", 3);
|
log.Debug($"({url}) = '{message}'", 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static T Retry<T>(Func<T> operation)
|
private T Retry<T>(Func<T> operation)
|
||||||
{
|
{
|
||||||
var retryCounter = 0;
|
var retryCounter = 0;
|
||||||
|
|
||||||
@ -115,9 +117,9 @@ namespace DistTestCore
|
|||||||
}
|
}
|
||||||
catch (Exception exception)
|
catch (Exception exception)
|
||||||
{
|
{
|
||||||
Timing.HttpCallRetryDelay();
|
timeSet.HttpCallRetryDelay();
|
||||||
retryCounter++;
|
retryCounter++;
|
||||||
if (retryCounter > Timing.HttpCallRetryCount())
|
if (retryCounter > timeSet.HttpCallRetryCount())
|
||||||
{
|
{
|
||||||
Assert.Fail(exception.ToString());
|
Assert.Fail(exception.ToString());
|
||||||
throw;
|
throw;
|
||||||
@ -140,10 +142,10 @@ namespace DistTestCore
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static HttpClient GetClient()
|
private HttpClient GetClient()
|
||||||
{
|
{
|
||||||
var client = new HttpClient();
|
var client = new HttpClient();
|
||||||
client.Timeout = Timing.HttpCallTimeout();
|
client.Timeout = timeSet.HttpCallTimeout();
|
||||||
return client;
|
return client;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -14,12 +14,14 @@ namespace DistTestCore.Metrics
|
|||||||
public class MetricsAccess : IMetricsAccess
|
public class MetricsAccess : IMetricsAccess
|
||||||
{
|
{
|
||||||
private readonly TestLog log;
|
private readonly TestLog log;
|
||||||
|
private readonly ITimeSet timeSet;
|
||||||
private readonly MetricsQuery query;
|
private readonly MetricsQuery query;
|
||||||
private readonly RunningContainer node;
|
private readonly RunningContainer node;
|
||||||
|
|
||||||
public MetricsAccess(TestLog log, MetricsQuery query, RunningContainer node)
|
public MetricsAccess(TestLog log, ITimeSet timeSet, MetricsQuery query, RunningContainer node)
|
||||||
{
|
{
|
||||||
this.log = log;
|
this.log = log;
|
||||||
|
this.timeSet = timeSet;
|
||||||
this.query = query;
|
this.query = query;
|
||||||
this.node = node;
|
this.node = node;
|
||||||
}
|
}
|
||||||
@ -47,7 +49,7 @@ namespace DistTestCore.Metrics
|
|||||||
{
|
{
|
||||||
var mostRecent = GetMostRecent(metricName);
|
var mostRecent = GetMostRecent(metricName);
|
||||||
if (mostRecent != null) return mostRecent;
|
if (mostRecent != null) return mostRecent;
|
||||||
if (DateTime.UtcNow - start > Timing.WaitForMetricTimeout())
|
if (DateTime.UtcNow - start > timeSet.WaitForMetricTimeout())
|
||||||
{
|
{
|
||||||
Assert.Fail($"Timeout: Unable to get metric '{metricName}'.");
|
Assert.Fail($"Timeout: Unable to get metric '{metricName}'.");
|
||||||
throw new TimeoutException();
|
throw new TimeoutException();
|
||||||
|
@ -28,8 +28,8 @@ namespace DistTestCore.Metrics
|
|||||||
|
|
||||||
public IMetricsAccess CreateMetricsAccess(RunningContainer codexContainer)
|
public IMetricsAccess CreateMetricsAccess(RunningContainer codexContainer)
|
||||||
{
|
{
|
||||||
var query = new MetricsQuery(lifecycle.Log, prometheusContainer);
|
var query = new MetricsQuery(lifecycle.Log, lifecycle.TimeSet, prometheusContainer);
|
||||||
return new MetricsAccess(lifecycle.Log, query, codexContainer);
|
return new MetricsAccess(lifecycle.Log, lifecycle.TimeSet, query, codexContainer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,12 +9,13 @@ namespace DistTestCore.Metrics
|
|||||||
{
|
{
|
||||||
private readonly Http http;
|
private readonly Http http;
|
||||||
|
|
||||||
public MetricsQuery(BaseLog log, RunningContainers runningContainers)
|
public MetricsQuery(BaseLog log, ITimeSet timeSet, RunningContainers runningContainers)
|
||||||
{
|
{
|
||||||
RunningContainers = runningContainers;
|
RunningContainers = runningContainers;
|
||||||
|
|
||||||
http = new Http(
|
http = new Http(
|
||||||
log,
|
log,
|
||||||
|
timeSet,
|
||||||
runningContainers.RunningPod.Cluster.IP,
|
runningContainers.RunningPod.Cluster.IP,
|
||||||
runningContainers.Containers[0].ServicePorts[0].Number,
|
runningContainers.Containers[0].ServicePorts[0].Number,
|
||||||
"api/v1");
|
"api/v1");
|
||||||
|
@ -10,10 +10,11 @@ namespace DistTestCore
|
|||||||
private readonly WorkflowCreator workflowCreator;
|
private readonly WorkflowCreator workflowCreator;
|
||||||
private DateTime testStart = DateTime.MinValue;
|
private DateTime testStart = DateTime.MinValue;
|
||||||
|
|
||||||
public TestLifecycle(TestLog log, Configuration configuration)
|
public TestLifecycle(TestLog log, Configuration configuration, ITimeSet timeSet)
|
||||||
{
|
{
|
||||||
Log = log;
|
Log = log;
|
||||||
workflowCreator = new WorkflowCreator(log, configuration.GetK8sConfiguration());
|
TimeSet = timeSet;
|
||||||
|
workflowCreator = new WorkflowCreator(log, configuration.GetK8sConfiguration(timeSet));
|
||||||
|
|
||||||
FileManager = new FileManager(Log, configuration);
|
FileManager = new FileManager(Log, configuration);
|
||||||
CodexStarter = new CodexStarter(this, workflowCreator);
|
CodexStarter = new CodexStarter(this, workflowCreator);
|
||||||
@ -23,6 +24,7 @@ namespace DistTestCore
|
|||||||
}
|
}
|
||||||
|
|
||||||
public TestLog Log { get; }
|
public TestLog Log { get; }
|
||||||
|
public ITimeSet TimeSet { get; }
|
||||||
public FileManager FileManager { get; }
|
public FileManager FileManager { get; }
|
||||||
public CodexStarter CodexStarter { get; }
|
public CodexStarter CodexStarter { get; }
|
||||||
public PrometheusStarter PrometheusStarter { get; }
|
public PrometheusStarter PrometheusStarter { get; }
|
||||||
|
@ -8,53 +8,11 @@ namespace DistTestCore
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class Timing
|
|
||||||
{
|
|
||||||
public static bool UseLongTimeouts { get; set; }
|
|
||||||
|
|
||||||
|
|
||||||
public static TimeSpan HttpCallTimeout()
|
|
||||||
{
|
|
||||||
return GetTimes().HttpCallTimeout();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static int HttpCallRetryCount()
|
|
||||||
{
|
|
||||||
return GetTimes().HttpCallRetryCount();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void HttpCallRetryDelay()
|
|
||||||
{
|
|
||||||
Time.Sleep(GetTimes().HttpCallRetryDelay());
|
|
||||||
}
|
|
||||||
|
|
||||||
public static TimeSpan K8sServiceDelay()
|
|
||||||
{
|
|
||||||
return GetTimes().WaitForK8sServiceDelay();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static TimeSpan K8sOperationTimeout()
|
|
||||||
{
|
|
||||||
return GetTimes().K8sOperationTimeout();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static TimeSpan WaitForMetricTimeout()
|
|
||||||
{
|
|
||||||
return GetTimes().WaitForMetricTimeout();
|
|
||||||
}
|
|
||||||
|
|
||||||
private static ITimeSet GetTimes()
|
|
||||||
{
|
|
||||||
if (UseLongTimeouts) return new LongTimeSet();
|
|
||||||
return new DefaultTimeSet();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public interface ITimeSet
|
public interface ITimeSet
|
||||||
{
|
{
|
||||||
TimeSpan HttpCallTimeout();
|
TimeSpan HttpCallTimeout();
|
||||||
int HttpCallRetryCount();
|
int HttpCallRetryCount();
|
||||||
TimeSpan HttpCallRetryDelay();
|
void HttpCallRetryDelay();
|
||||||
TimeSpan WaitForK8sServiceDelay();
|
TimeSpan WaitForK8sServiceDelay();
|
||||||
TimeSpan K8sOperationTimeout();
|
TimeSpan K8sOperationTimeout();
|
||||||
TimeSpan WaitForMetricTimeout();
|
TimeSpan WaitForMetricTimeout();
|
||||||
@ -72,9 +30,9 @@ namespace DistTestCore
|
|||||||
return 5;
|
return 5;
|
||||||
}
|
}
|
||||||
|
|
||||||
public TimeSpan HttpCallRetryDelay()
|
public void HttpCallRetryDelay()
|
||||||
{
|
{
|
||||||
return TimeSpan.FromSeconds(3);
|
Time.Sleep(TimeSpan.FromSeconds(3));
|
||||||
}
|
}
|
||||||
|
|
||||||
public TimeSpan WaitForK8sServiceDelay()
|
public TimeSpan WaitForK8sServiceDelay()
|
||||||
@ -105,9 +63,9 @@ namespace DistTestCore
|
|||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
public TimeSpan HttpCallRetryDelay()
|
public void HttpCallRetryDelay()
|
||||||
{
|
{
|
||||||
return TimeSpan.FromMinutes(5);
|
Time.Sleep(TimeSpan.FromMinutes(5));
|
||||||
}
|
}
|
||||||
|
|
||||||
public TimeSpan WaitForK8sServiceDelay()
|
public TimeSpan WaitForK8sServiceDelay()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user