Free cookie consent management tool by TermsFeed Policy Generator

source: branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Services.Hive.Tests/ServiceTests.cs @ 6267

Last change on this file since 6267 was 6267, checked in by cneumuel, 13 years ago

#1233

  • extended statistics recording:
    • execution times of users are captured
    • execution times and start-to-finish time of finished jobs is captured (to computer hive overhead)
    • data of deleted jobs is automatically captured in DeletedJobStatistics
  • changed ExecutionTime type in database from string to float (milliseconds are stored instead of TimeSpan.ToString())
  • added IsPrivileged field to job to indicate if it should be executed in a privileged sandbox
  • added CpuUtilization field to slave to be able to report cpu utilization
  • added GetJobsByResourceId to retrieve all jobs which are currently beeing calculated in a slave(-group)
  • TransactionManager now allows to use serializable tranactions (used for lifecycle trigger)
File size: 16.7 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2010 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
4 *
5 * This file is part of HeuristicLab.
6 *
7 * HeuristicLab is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * HeuristicLab is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
19 */
20#endregion
21
22using System;
23using System.Collections.Generic;
24using System.Linq;
25using HeuristicLab.Services.Hive.Common;
26using HeuristicLab.Services.Hive.Common.DataTransfer;
27using HeuristicLab.Services.Hive.Common.ServiceContracts;
28using Microsoft.VisualStudio.TestTools.UnitTesting;
29
30namespace HeuristicLab.Services.Hive.Tests {
31
32  using DT = HeuristicLab.Services.Hive.Common.DataTransfer;
33
34  [TestClass]
35  public class ServiceTests {
36
37    [ClassInitialize]
38    public static void MyClassInitialize(TestContext testContext) {
39      ServiceLocator.Instance = new MockServiceLocator(ServiceLocator.Instance);
40    }
41
42    private IHiveService GetLocalService() {
43      return new HiveService();
44    }
45
46    [TestMethod]
47    public void TestJobs() {
48      var service = GetLocalService();
49
50      // create hive experiment
51      DT.HiveExperiment experiment = new DT.HiveExperiment() {
52        Name = "TestExperiment",
53        Description = ""
54      };
55
56      // create job
57      DT.Job job = new DT.Job() {
58        CoresNeeded = 1,
59        MemoryNeeded = 0,
60        Priority = 0
61      };
62      job.State = JobState.Offline;
63      job.StateLog.Add(new StateLog { State = JobState.Offline, DateTime = DateTime.Now });
64
65      DT.JobData jobData = new DT.JobData() {
66        //Data = PersistenceUtil.Serialize(new MockJob(500, true))
67        Data = new byte[10000]
68      };
69
70      // create plugin
71      DT.Plugin plugin1 = new DT.Plugin();
72      plugin1.Name = "Tests.MyPlugin";
73      plugin1.Version = new Version("1.0.0.0");
74      plugin1.UserId = Guid.Empty;
75      plugin1.IsLocal = true;
76      plugin1.DateCreated = DateTime.Now;
77
78      DT.PluginData pluginData1 = new DT.PluginData();
79      pluginData1.FileName = "Tests.MyPlugin-1.0.dll";
80      pluginData1.Data = new byte[] { 0, 1, 2, 3, 4, 5 };
81
82      plugin1.Id = service.AddPlugin(plugin1, new List<PluginData> { pluginData1 });
83      pluginData1.PluginId = plugin1.Id;
84
85      // add plugin
86      job.PluginsNeededIds.Add(plugin1.Id);
87
88      // create slave
89      DT.Slave slave = new Slave();
90      slave.Id = Guid.NewGuid();
91      slave.Name = "TestSlave";
92      slave.Memory = 1024;
93      slave.Cores = 4;
94      slave.CpuSpeed = 2800;
95      slave.OperatingSystem = "Windows 3.11";
96      slave.CpuArchitecture = CpuArchitecture.x64;
97
98      // add slave
99      service.AddSlave(slave);
100
101      // add hive experiment
102      experiment.Id = service.AddHiveExperiment(experiment);
103
104      // add job
105      job.HiveExperimentId = experiment.Id;
106      job.Id = service.AddJob(job, jobData, new List<Guid> { slave.Id });
107     
108      // test job
109      DT.Job jobLoaded = service.GetJob(job.Id);
110      Assert.AreEqual(job.Id, jobLoaded.Id);
111      Assert.AreEqual(job.CoresNeeded, jobLoaded.CoresNeeded);
112      Assert.AreEqual(job.MemoryNeeded, jobLoaded.MemoryNeeded);
113      Assert.AreEqual(job.Priority, jobLoaded.Priority);
114      Assert.AreEqual(JobState.Waiting, jobLoaded.State);
115      Assert.IsTrue(job.PluginsNeededIds.SequenceEqual(jobLoaded.PluginsNeededIds));
116      Assert.AreEqual(job.HiveExperimentId, jobLoaded.HiveExperimentId);
117
118      DT.JobData jobDataLoaded = service.GetJobData(job.Id);
119      Assert.AreEqual(job.Id, jobDataLoaded.JobId);
120      Assert.IsTrue(jobData.Data.SequenceEqual(jobDataLoaded.Data));
121
122      // test hive experiment
123      DT.HiveExperiment experimentLoaded = service.GetHiveExperiment(experiment.Id);
124      Assert.AreEqual(experiment.Id, experimentLoaded.Id);
125      Assert.AreEqual(experiment.Name, experimentLoaded.Name);
126      Assert.AreEqual(experiment.Description, experimentLoaded.Description);
127
128      // test assigned ressources
129      var actions = service.Heartbeat(new Heartbeat() { SlaveId = slave.Id, AssignJob = true, FreeCores = 4, FreeMemory = 1024, JobProgress = new Dictionary<Guid, TimeSpan>() });
130      Assert.AreEqual(1, actions.Count);
131      Assert.AreEqual(MessageContainer.MessageType.CalculateJob, actions[0].Message);
132      Assert.AreEqual(job.Id, actions[0].JobId);
133
134      jobLoaded = service.GetJob(job.Id);
135      Assert.AreEqual(JobState.Transferring, jobLoaded.State);
136
137      // slave is responsible for updating state to 'Calculating'
138      service.UpdateJobState(jobLoaded.Id, JobState.Calculating, slave.Id, null, null);
139
140      // send progress
141      var progress = new Dictionary<Guid, TimeSpan>();
142      progress.Add(job.Id, new TimeSpan(1, 5, 10, 20, 30));
143      actions = service.Heartbeat(new Heartbeat() { SlaveId = slave.Id, AssignJob = true, FreeCores = 3, FreeMemory = 1024, JobProgress = progress });
144      Assert.AreEqual(0, actions.Count);
145
146      // the job should be in state 'Calculating' now
147      jobLoaded = service.GetJob(job.Id);
148      Assert.AreEqual(JobState.Calculating, jobLoaded.State);
149      Assert.AreEqual(new TimeSpan(1, 5, 10, 20, 30), jobLoaded.ExecutionTime);
150
151      // test if the job is returned for the resource
152      var jobsBySlave = service.GetJobsByResourceId(slave.Id);
153      Assert.AreEqual(1, jobsBySlave.Count());
154      Assert.AreEqual(job.Id, jobsBySlave.Single().Id);
155     
156      // set it to finished
157      service.UpdateJobState(jobLoaded.Id, JobState.Finished, slave.Id, null, null);
158
159      // test if the job is returned for the resource
160      var jobsBySlave2 = service.GetJobsByResourceId(slave.Id);
161      Assert.AreEqual(0, jobsBySlave2.Count());
162
163      // delete
164      service.DeleteHiveExperiment(experiment.Id);
165      Assert.AreEqual(null, service.GetHiveExperiment(experiment.Id));
166      Assert.AreEqual(null, service.GetJob(job.Id));
167      Assert.AreEqual(null, service.GetJobData(job.Id));
168
169      // send another heartbeat with the deleted job; the server should command the abortion of the job
170      actions = service.Heartbeat(new Heartbeat() { SlaveId = slave.Id, AssignJob = true, FreeCores = 3, FreeMemory = 1024, JobProgress = progress });
171      Assert.AreEqual(1, actions.Count);
172      Assert.AreEqual(MessageContainer.MessageType.AbortJob, actions[0].Message);
173      Assert.AreEqual(job.Id, actions[0].JobId);
174
175      // delete slave
176      service.DeleteSlave(slave.Id);
177    }
178
179    List<DT.Job> jobs = new List<DT.Job>();
180   
181    [TestMethod]
182    public void TestParentJobs() {
183      var service = GetLocalService();
184
185      // create hive experiment
186      DT.HiveExperiment experiment = new DT.HiveExperiment() {
187        Name = "TestExperiment",
188        Description = ""
189      };
190
191      // create parent job
192      DT.Job parentJob = new DT.Job() {
193        CoresNeeded = 1,
194        MemoryNeeded = 0,
195        Priority = 0,
196        IsParentJob = true,
197        FinishWhenChildJobsFinished = true
198      };
199      parentJob.State = JobState.Offline;
200      parentJob.StateLog.Add(new StateLog { State = JobState.Offline, DateTime = DateTime.Now });
201
202      DT.JobData parentJobData = new DT.JobData() { Data = new byte[0] };
203
204      // create child job
205      DT.Job childJob = new DT.Job() {
206        CoresNeeded = 1,
207        MemoryNeeded = 0,
208        Priority = 0
209      };
210      childJob.State = JobState.Offline;
211      childJob.StateLog.Add(new StateLog { State = JobState.Offline, DateTime = DateTime.Now });
212
213      DT.JobData childJobData = new DT.JobData() { Data = new byte[1000] };
214
215      // create slave
216      DT.Slave slave = new Slave();
217      slave.Id = Guid.NewGuid();
218      slave.Name = "TestSlave";
219      slave.Memory = 1024;
220      slave.Cores = 4;
221      slave.CpuSpeed = 2800;
222      slave.OperatingSystem = "Windows 3.11";
223      slave.CpuArchitecture = CpuArchitecture.x64;
224
225      // add slave
226      service.AddSlave(slave);
227
228      // add hive experiment
229      experiment.Id = service.AddHiveExperiment(experiment);
230
231      // add parent job
232      parentJob.HiveExperimentId = experiment.Id;
233      parentJob.Id = service.AddJob(parentJob, parentJobData, new List<Guid> { slave.Id });
234
235      // add child job
236      childJob.HiveExperimentId = experiment.Id;
237      childJob.Id = service.AddChildJob(parentJob.Id, childJob, childJobData);
238      childJob.ParentJobId = parentJob.Id;
239
240      // test child job
241      var childJobLoaded = service.GetJob(childJob.Id);
242      Assert.AreEqual(childJob.ParentJobId, childJobLoaded.ParentJobId);
243      Assert.AreEqual(childJob.HiveExperimentId, childJobLoaded.HiveExperimentId);
244      Assert.AreEqual(JobState.Waiting, childJobLoaded.State);
245      Assert.AreEqual(false, childJobLoaded.FinishWhenChildJobsFinished);
246      Assert.AreEqual(false, childJobLoaded.IsParentJob);
247
248      // test parent job
249      var parentJobLoaded = service.GetJob(parentJob.Id);
250      Assert.AreEqual(parentJob.HiveExperimentId, parentJobLoaded.HiveExperimentId);
251      Assert.AreEqual(JobState.Waiting, parentJobLoaded.State);
252      Assert.AreEqual(true, parentJobLoaded.FinishWhenChildJobsFinished);
253      Assert.AreEqual(true, parentJobLoaded.IsParentJob);
254
255      // test heartbeat
256      var actions = service.Heartbeat(new Heartbeat() { SlaveId = slave.Id, AssignJob = true, FreeCores = 4, FreeMemory = 1024, JobProgress = new Dictionary<Guid, TimeSpan>() });
257      Assert.AreEqual(1, actions.Count); // only the child job should be assigned
258      Assert.AreEqual(MessageContainer.MessageType.CalculateJob, actions[0].Message);
259      Assert.AreEqual(childJob.Id, actions[0].JobId);
260
261      // lifecycle - let it process one server-heartbeat; the parent job must NOT be set to finished
262      service.TriggerLifecycle(true);
263
264      parentJobLoaded = service.GetJob(parentJob.Id);
265      Assert.AreEqual(JobState.Waiting, parentJobLoaded.State);
266
267      // set child job to finished
268      childJobLoaded = service.UpdateJobState(childJobLoaded.Id, JobState.Finished, slave.Id, null, null);
269
270      // lifecycle - let it process one server-heartbeat; this should set the parent job to finished
271      service.TriggerLifecycle(true);
272
273      // test if parent job is finished
274      parentJobLoaded = service.GetJob(parentJob.Id);
275      Assert.AreEqual(JobState.Finished, parentJobLoaded.State);
276
277      // delete experiment
278      service.DeleteHiveExperiment(experiment.Id);
279      Assert.AreEqual(null, service.GetJob(parentJob.Id));
280      Assert.AreEqual(null, service.GetJob(childJob.Id));
281
282      service.DeleteSlave(slave.Id);
283    }
284
285    //[TestMethod]
286    //public void TestHeartbeats() {
287    //  var service = GetLocalService();
288    //  // check if group already exists and delete
289    //  var existingSlaveGroup = service.GetSlaveGroups().SingleOrDefault(g => g.Name == "TestGroup");
290    //  if (existingSlaveGroup != null) {
291    //    var slavesToDelete = service.GetSlaves().Where(s => s.ParentResourceId == existingSlaveGroup.Id);
292    //    foreach (var slave in slavesToDelete) service.DeleteSlave(slave.Id);
293    //    service.DeleteSlaveGroup(existingSlaveGroup.Id);
294    //  }
295
296    //  Guid groupId = service.AddSlaveGroup(new SlaveGroup() { Name = "TestGroup", Description = "Used for unit tests" });
297
298    //  // create slaves
299    //  var slaves = new List<DT.Slave>();
300    //  for (int i = 0; i < 1; i++) {
301    //    DT.Slave slave = new DT.Slave() {
302    //      Cores = 2,
303    //      Memory = 4096,
304    //      Name = "Slave " + i,
305    //      IsAllowedToCalculate = true,
306    //      SlaveState = SlaveState.Idle,
307    //      CpuSpeed = 2800,
308    //      FreeCores = 2,
309    //      FreeMemory = 3000
310    //    };
311    //    // check if slave with this name already exists and delete
312    //    var existingSlave = service.GetSlaves().Where(s => s.Name == slave.Name).SingleOrDefault();
313    //    if (existingSlave != null) service.DeleteSlave(existingSlave.Id);
314
315    //    slave.Id = service.AddSlave(slave);
316    //    service.AddResourceToGroup(groupId, slave.Id);
317    //    slaves.Add(slave);
318    //  }
319
320    //  // create jobs with different group, they should not be assigned
321    //  existingSlaveGroup = service.GetSlaveGroups().SingleOrDefault(g => g.Name == "DummyGroup");
322    //  if (existingSlaveGroup != null) service.DeleteSlaveGroup(existingSlaveGroup.Id);
323
324    //  Guid dummyGroupId = service.AddSlaveGroup(new SlaveGroup() { Name = "DummyGroup", Description = "Used for unit tests; jobs from this group shall not be calculated" });
325    //  // create dummy jobs
326    //  var dummyJobs = new List<Job>();
327    //  for (int i = 0; i < 2; i++) {
328    //    Job job = new Job() {
329    //      CoresNeeded = 1, MemoryNeeded = 0
330    //    };
331    //    JobData jobData = new JobData() { Data = PersistenceUtil.Serialize(new MockJob(500, false)) };
332    //    job.Id = service.AddJob(job, jobData, new List<Guid> { dummyGroupId });
333    //    dummyJobs.Add(job);
334    //  }
335
336    //  // create jobs
337    //  for (int i = 0; i < 2; i++) {
338    //    Job job = new Job() {
339    //      CoresNeeded = 1, MemoryNeeded = 0
340    //    };
341    //    JobData jobData = new JobData() { Data = PersistenceUtil.Serialize(new MockJob(500, false)) };
342    //    job.Id = service.AddJob(job, jobData, new List<Guid> { groupId });
343    //    jobs.Add(job);
344    //  }
345
346    //  // send heartbeats
347    //  foreach (var slave in slaves) {
348    //    new Thread(new ParameterizedThreadStart(RunSlaveThread)).Start(slave);
349    //  }
350
351    //  IEnumerable<LightweightJob> lightweightJobs;
352    //  do {
353    //    Thread.Sleep(500);
354    //    lightweightJobs = service.GetLightweightJobs(jobs.Select(x => x.Id));
355    //  } while (!lightweightJobs.All(x => x.State == JobState.Finished));
356
357    //  // delete slaves
358    //  foreach (var slave in slaves) {
359    //    service.DeleteSlave(slave.Id);
360    //    Assert.AreEqual(null, service.GetSlave(slave.Id));
361    //  }
362
363    //  // delete groups
364    //  service.DeleteSlaveGroup(groupId);
365    //  service.DeleteSlaveGroup(dummyGroupId);
366
367    //  // delete jobs
368    //  foreach (var job in jobs) {
369    //    service.DeleteJob(job.Id);
370    //  }
371
372    //  // delete dummy jobs
373    //  foreach (var job in dummyJobs) {
374    //    service.DeleteJob(job.Id);
375    //  }
376    //}
377
378    //public void RunSlaveThread(object slaveobj) {
379    //  try {
380    //    var service = GetLocalService();
381    //    Slave slave = (Slave)slaveobj;
382    //    int freeCores = slave.Cores.Value;
383
384    //    for (int i = 0; i < 10; i++) {
385
386    //      var messages = service.Heartbeat(new Heartbeat() { SlaveId = slave.Id, FreeMemory = 2423, FreeCores = freeCores, JobProgress = new Dictionary<Guid, TimeSpan>() });
387    //      if (messages.Count == 0) {
388    //        Debug.WriteLine("No job available");
389    //        return; // no more jobs
390    //      }
391
392    //      Debug.WriteLine("Messages: {0}", string.Join(", ", messages.Select(m => m.Message)));
393
394    //      Assert.IsTrue(messages.Where(x => x.Message == MessageContainer.MessageType.AbortJob).Count() == 0);
395    //      Assert.IsTrue(messages.Where(x => x.Message == MessageContainer.MessageType.SayHello).Count() == 0);
396    //      Assert.IsTrue(messages.Where(x => x.Message == MessageContainer.MessageType.PauseJob).Count() == 0);
397
398    //      var calculateJobMessage = messages.Where(x => x.Message == MessageContainer.MessageType.CalculateJob).SingleOrDefault();
399    //      if (calculateJobMessage != null) {
400    //        if (!jobs.Select(j => j.Id).Contains(calculateJobMessage.JobId))
401    //          Assert.Fail("Got job which was not assigned to the slavegroup");
402
403    //        Debug.WriteLine("Job available, calculating");
404    //        Job job = service.GetJob(calculateJobMessage.JobId);
405
406    //        JobData jobData = service.GetJobData(job.Id);
407    //        IJob deserializedJob = PersistenceUtil.Deserialize<IJob>(jobData.Data);
408    //        deserializedJob.Start();
409    //        job.SetState(JobState.Finished);
410    //        jobs.Where(x => x.Id == job.Id).Single().SetState(JobState.Finished);
411    //        jobData.Data = PersistenceUtil.Serialize(deserializedJob);
412    //        service.UpdateJobData(job, jobData);
413    //        Debug.WriteLine("finished calculating");
414    //      }
415    //    }
416    //  }
417    //  catch (Exception e) {
418    //    Assert.Fail(e.Message, e);
419    //  }
420    //}
421  }
422}
Note: See TracBrowser for help on using the repository browser.