Free cookie consent management tool by TermsFeed Policy Generator

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

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

#1233

  • fixed handling of StateLog in DataLayer
  • extended unit tests
  • changed style of service calls to OKB-like style (using delegates)
  • added possibility that parent jobs can be finished immediately when child jobs are finished
File size: 15.8 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 System.Threading;
26using HeuristicLab.Services.Hive.Common;
27using HeuristicLab.Services.Hive.Common.DataTransfer;
28using HeuristicLab.Services.Hive.Common.ServiceContracts;
29using Microsoft.VisualStudio.TestTools.UnitTesting;
30
31namespace HeuristicLab.Services.Hive.Tests {
32
33  using DT = HeuristicLab.Services.Hive.Common.DataTransfer;
34
35  [TestClass]
36  public class ServiceTests {
37
38    [ClassInitialize]
39    public static void MyClassInitialize(TestContext testContext) {
40      PluginLoader.pluginAssemblies.Any();
41      ServiceLocator.Instance = new MockServiceLocator(ServiceLocator.Instance);
42    }
43
44    private IHiveService GetLocalService() {
45      return new HiveService();
46    }
47
48    [TestMethod]
49    public void TestJobs() {
50      var service = GetLocalService();
51
52      // create hive experiment
53      DT.HiveExperiment experiment = new DT.HiveExperiment() {
54        Name = "TestExperiment",
55        Description = ""
56      };
57
58      // create job
59      DT.Job job = new DT.Job() {
60        CoresNeeded = 1,
61        MemoryNeeded = 0,
62        Priority = 0
63      };
64      job.SetState(JobState.Offline);
65
66      DT.JobData jobData = new DT.JobData() {
67        //Data = PersistenceUtil.Serialize(new MockJob(500, true))
68        Data = new byte[10000]
69      };
70
71      // create plugin
72      DT.Plugin plugin1 = new DT.Plugin();
73      plugin1.Name = "Tests.MyPlugin";
74      plugin1.Version = new Version("1.0.0.0");
75      plugin1.UserId = Guid.Empty;
76      plugin1.IsLocal = true;
77      plugin1.DateCreated = DateTime.Now;
78
79      DT.PluginData pluginData1 = new DT.PluginData();
80      pluginData1.FileName = "Tests.MyPlugin-1.0.dll";
81      pluginData1.Data = new byte[] { 0, 1, 2, 3, 4, 5 };
82
83      plugin1.Id = service.AddPlugin(plugin1, new List<PluginData> { pluginData1 });
84      pluginData1.PluginId = plugin1.Id;
85
86      // add plugin
87      job.PluginsNeededIds.Add(plugin1.Id);
88
89      // create slave
90      DT.Slave slave = new Slave();
91      slave.Id = Guid.NewGuid();
92      slave.Name = "TestSlave";
93      slave.Memory = 1024;
94      slave.Cores = 4;
95      slave.CpuSpeed = 2800;
96      slave.OperatingSystem = "Windows 3.11";
97      slave.CpuArchitecture = CpuArchitecture.x64;
98
99      // add slave
100      service.AddSlave(slave);
101
102      // add job
103      job.Id = service.AddJob(job, jobData, new List<Guid> { slave.Id });
104      experiment.RootJobId = job.Id;
105
106      // add hive experiment
107      experiment.Id = service.AddHiveExperiment(experiment);
108
109      // test job
110      DT.Job jobLoaded = service.GetJob(job.Id);
111      Assert.AreEqual(job.Id, jobLoaded.Id);
112      Assert.AreEqual(job.CoresNeeded, jobLoaded.CoresNeeded);
113      Assert.AreEqual(job.MemoryNeeded, jobLoaded.MemoryNeeded);
114      Assert.AreEqual(job.Priority, jobLoaded.Priority);
115      Assert.AreEqual(JobState.Waiting, jobLoaded.State);
116      Assert.IsTrue(job.PluginsNeededIds.SequenceEqual(jobLoaded.PluginsNeededIds));
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      Assert.AreEqual(experiment.RootJobId, experimentLoaded.RootJobId);
128
129      // test assigned ressources
130      var actions = service.Heartbeat(new Heartbeat() { SlaveId = slave.Id, AssignJob = true, FreeCores = 4, FreeMemory = 1024, JobProgress = new Dictionary<Guid, TimeSpan>() });
131      Assert.AreEqual(1, actions.Count);
132      Assert.AreEqual(MessageContainer.MessageType.CalculateJob, actions[0].Message);
133      Assert.AreEqual(job.Id, actions[0].JobId);
134
135      jobLoaded = service.GetJob(job.Id);
136      Assert.AreEqual(JobState.Transferring, jobLoaded.State);
137
138      // send progress
139      var progress = new Dictionary<Guid, TimeSpan>();
140      progress.Add(job.Id, new TimeSpan(1, 5, 10, 20, 30));
141      actions = service.Heartbeat(new Heartbeat() { SlaveId = slave.Id, AssignJob = true, FreeCores = 3, FreeMemory = 1024, JobProgress = progress });
142      Assert.AreEqual(0, actions.Count);
143
144      // the job should be in state 'Calculating' now
145      jobLoaded = service.GetJob(job.Id);
146      Assert.AreEqual(JobState.Calculating, jobLoaded.State);
147      Assert.AreEqual(new TimeSpan(1, 5, 10, 20, 30), jobLoaded.ExecutionTime.Value);
148
149      // delete
150      service.DeleteHiveExperiment(experiment.Id);
151      Assert.AreEqual(null, service.GetHiveExperiment(experiment.Id));
152      Assert.AreEqual(null, service.GetJob(job.Id));
153      Assert.AreEqual(null, service.GetJobData(job.Id));
154
155      // send another heartbeat with the deleted job; the server should command the abortion of the job
156      actions = service.Heartbeat(new Heartbeat() { SlaveId = slave.Id, AssignJob = true, FreeCores = 3, FreeMemory = 1024, JobProgress = progress });
157      Assert.AreEqual(1, actions.Count);
158      Assert.AreEqual(MessageContainer.MessageType.AbortJob, actions[0].Message);
159      Assert.AreEqual(job.Id, actions[0].JobId);
160
161      // delete slave
162      service.DeleteSlave(slave.Id);
163    }
164
165    List<DT.Job> jobs = new List<DT.Job>();
166
167
168    [TestMethod]
169    public void TestParentJobs() {
170      var service = GetLocalService();
171
172      // create hive experiment
173      DT.HiveExperiment experiment = new DT.HiveExperiment() {
174        Name = "TestExperiment",
175        Description = ""
176      };
177
178      // create parent job
179      DT.Job parentJob = new DT.Job() {
180        CoresNeeded = 1,
181        MemoryNeeded = 0,
182        Priority = 0,
183        IsParentJob = true,
184        FinishWhenChildJobsFinished = true
185      };
186      parentJob.SetState(JobState.Offline);
187
188      DT.JobData parentJobData = new DT.JobData() { Data = new byte[0] };
189
190      // create child job
191      DT.Job childJob = new DT.Job() {
192        CoresNeeded = 1,
193        MemoryNeeded = 0,
194        Priority = 0
195      };
196      parentJob.SetState(JobState.Offline);
197
198      DT.JobData childJobData = new DT.JobData() { Data = new byte[1000] };
199
200      // create slave
201      DT.Slave slave = new Slave();
202      slave.Id = Guid.NewGuid();
203      slave.Name = "TestSlave";
204      slave.Memory = 1024;
205      slave.Cores = 4;
206      slave.CpuSpeed = 2800;
207      slave.OperatingSystem = "Windows 3.11";
208      slave.CpuArchitecture = CpuArchitecture.x64;
209
210      // add slave
211      service.AddSlave(slave);
212
213      // add parent job
214      parentJob.Id = service.AddJob(parentJob, parentJobData, new List<Guid> { slave.Id });
215      experiment.RootJobId = parentJob.Id;
216
217      // add child job
218      childJob.Id = service.AddChildJob(parentJob.Id, childJob, childJobData);
219      childJob.ParentJobId = parentJob.Id;
220
221      // add hive experiment
222      experiment.Id = service.AddHiveExperiment(experiment);
223
224      // test child job
225      var childJobLoaded = service.GetJob(childJob.Id);
226      Assert.AreEqual(childJob.ParentJobId, childJobLoaded.ParentJobId);
227      Assert.AreEqual(JobState.Waiting, childJobLoaded.State);
228      Assert.AreEqual(false, childJobLoaded.FinishWhenChildJobsFinished);
229      Assert.AreEqual(false, childJobLoaded.IsParentJob);
230
231      // test parent job
232      var parentJobLoaded = service.GetJob(parentJob.Id);
233      Assert.AreEqual(JobState.Waiting, parentJobLoaded.State);
234      Assert.AreEqual(true, parentJobLoaded.FinishWhenChildJobsFinished);
235      Assert.AreEqual(true, parentJobLoaded.IsParentJob);
236
237      // test heartbeat
238      var actions = service.Heartbeat(new Heartbeat() { SlaveId = slave.Id, AssignJob = true, FreeCores = 4, FreeMemory = 1024, JobProgress = new Dictionary<Guid, TimeSpan>() });
239      Assert.AreEqual(1, actions.Count); // only the child job should be assigned
240      Assert.AreEqual(MessageContainer.MessageType.CalculateJob, actions[0].Message);
241      Assert.AreEqual(childJob.Id, actions[0].JobId);
242
243      // lifecycle - let it process one server-heartbeat; the parent job must NOT be set to finished
244      var lifecycleManager = new LifecycleManager();
245      lifecycleManager.Start();
246      Thread.Sleep(1000);
247      lifecycleManager.Stop();
248
249      parentJobLoaded = service.GetJob(parentJob.Id);
250      Assert.AreEqual(JobState.Waiting, parentJobLoaded.State);
251
252      // set child job to finished
253      childJobLoaded.SetState(JobState.Finished, slave.Id, "");
254      service.UpdateJob(childJobLoaded);
255
256      // lifecycle - let it process one server-heartbeat; this should set the parent job to finished
257      lifecycleManager.Start();
258      Thread.Sleep(1000);
259      lifecycleManager.Stop();
260
261      // test if parent job is finished
262      parentJobLoaded = service.GetJob(parentJob.Id);
263      Assert.AreEqual(JobState.Finished, parentJobLoaded.State);
264
265      // delete experiment
266      service.DeleteHiveExperiment(experiment.Id);
267      Assert.AreEqual(null, service.GetJob(parentJob.Id));
268      Assert.AreEqual(null, service.GetJob(childJob.Id));
269
270      service.DeleteSlave(slave.Id);
271    }
272
273    //[TestMethod]
274    //public void TestHeartbeats() {
275    //  var service = GetLocalService();
276    //  // check if group already exists and delete
277    //  var existingSlaveGroup = service.GetSlaveGroups().SingleOrDefault(g => g.Name == "TestGroup");
278    //  if (existingSlaveGroup != null) {
279    //    var slavesToDelete = service.GetSlaves().Where(s => s.ParentResourceId == existingSlaveGroup.Id);
280    //    foreach (var slave in slavesToDelete) service.DeleteSlave(slave.Id);
281    //    service.DeleteSlaveGroup(existingSlaveGroup.Id);
282    //  }
283
284    //  Guid groupId = service.AddSlaveGroup(new SlaveGroup() { Name = "TestGroup", Description = "Used for unit tests" });
285
286    //  // create slaves
287    //  var slaves = new List<DT.Slave>();
288    //  for (int i = 0; i < 1; i++) {
289    //    DT.Slave slave = new DT.Slave() {
290    //      Cores = 2,
291    //      Memory = 4096,
292    //      Name = "Slave " + i,
293    //      IsAllowedToCalculate = true,
294    //      SlaveState = SlaveState.Idle,
295    //      CpuSpeed = 2800,
296    //      FreeCores = 2,
297    //      FreeMemory = 3000
298    //    };
299    //    // check if slave with this name already exists and delete
300    //    var existingSlave = service.GetSlaves().Where(s => s.Name == slave.Name).SingleOrDefault();
301    //    if (existingSlave != null) service.DeleteSlave(existingSlave.Id);
302
303    //    slave.Id = service.AddSlave(slave);
304    //    service.AddResourceToGroup(groupId, slave.Id);
305    //    slaves.Add(slave);
306    //  }
307
308    //  // create jobs with different group, they should not be assigned
309    //  existingSlaveGroup = service.GetSlaveGroups().SingleOrDefault(g => g.Name == "DummyGroup");
310    //  if (existingSlaveGroup != null) service.DeleteSlaveGroup(existingSlaveGroup.Id);
311
312    //  Guid dummyGroupId = service.AddSlaveGroup(new SlaveGroup() { Name = "DummyGroup", Description = "Used for unit tests; jobs from this group shall not be calculated" });
313    //  // create dummy jobs
314    //  var dummyJobs = new List<Job>();
315    //  for (int i = 0; i < 2; i++) {
316    //    Job job = new Job() {
317    //      CoresNeeded = 1, MemoryNeeded = 0
318    //    };
319    //    JobData jobData = new JobData() { Data = PersistenceUtil.Serialize(new MockJob(500, false)) };
320    //    job.Id = service.AddJob(job, jobData, new List<Guid> { dummyGroupId });
321    //    dummyJobs.Add(job);
322    //  }
323
324    //  // create jobs
325    //  for (int i = 0; i < 2; i++) {
326    //    Job job = new Job() {
327    //      CoresNeeded = 1, MemoryNeeded = 0
328    //    };
329    //    JobData jobData = new JobData() { Data = PersistenceUtil.Serialize(new MockJob(500, false)) };
330    //    job.Id = service.AddJob(job, jobData, new List<Guid> { groupId });
331    //    jobs.Add(job);
332    //  }
333
334    //  // send heartbeats
335    //  foreach (var slave in slaves) {
336    //    new Thread(new ParameterizedThreadStart(RunSlaveThread)).Start(slave);
337    //  }
338
339    //  IEnumerable<LightweightJob> lightweightJobs;
340    //  do {
341    //    Thread.Sleep(500);
342    //    lightweightJobs = service.GetLightweightJobs(jobs.Select(x => x.Id));
343    //  } while (!lightweightJobs.All(x => x.State == JobState.Finished));
344
345    //  // delete slaves
346    //  foreach (var slave in slaves) {
347    //    service.DeleteSlave(slave.Id);
348    //    Assert.AreEqual(null, service.GetSlave(slave.Id));
349    //  }
350
351    //  // delete groups
352    //  service.DeleteSlaveGroup(groupId);
353    //  service.DeleteSlaveGroup(dummyGroupId);
354
355    //  // delete jobs
356    //  foreach (var job in jobs) {
357    //    service.DeleteJob(job.Id);
358    //  }
359
360    //  // delete dummy jobs
361    //  foreach (var job in dummyJobs) {
362    //    service.DeleteJob(job.Id);
363    //  }
364    //}
365
366    //public void RunSlaveThread(object slaveobj) {
367    //  try {
368    //    var service = GetLocalService();
369    //    Slave slave = (Slave)slaveobj;
370    //    int freeCores = slave.Cores.Value;
371
372    //    for (int i = 0; i < 10; i++) {
373
374    //      var messages = service.Heartbeat(new Heartbeat() { SlaveId = slave.Id, FreeMemory = 2423, FreeCores = freeCores, JobProgress = new Dictionary<Guid, TimeSpan>() });
375    //      if (messages.Count == 0) {
376    //        Debug.WriteLine("No job available");
377    //        return; // no more jobs
378    //      }
379
380    //      Debug.WriteLine("Messages: {0}", string.Join(", ", messages.Select(m => m.Message)));
381
382    //      Assert.IsTrue(messages.Where(x => x.Message == MessageContainer.MessageType.AbortJob).Count() == 0);
383    //      Assert.IsTrue(messages.Where(x => x.Message == MessageContainer.MessageType.SayHello).Count() == 0);
384    //      Assert.IsTrue(messages.Where(x => x.Message == MessageContainer.MessageType.PauseJob).Count() == 0);
385
386    //      var calculateJobMessage = messages.Where(x => x.Message == MessageContainer.MessageType.CalculateJob).SingleOrDefault();
387    //      if (calculateJobMessage != null) {
388    //        if (!jobs.Select(j => j.Id).Contains(calculateJobMessage.JobId))
389    //          Assert.Fail("Got job which was not assigned to the slavegroup");
390
391    //        Debug.WriteLine("Job available, calculating");
392    //        Job job = service.GetJob(calculateJobMessage.JobId);
393
394    //        JobData jobData = service.GetJobData(job.Id);
395    //        IJob deserializedJob = PersistenceUtil.Deserialize<IJob>(jobData.Data);
396    //        deserializedJob.Start();
397    //        job.SetState(JobState.Finished);
398    //        jobs.Where(x => x.Id == job.Id).Single().SetState(JobState.Finished);
399    //        jobData.Data = PersistenceUtil.Serialize(deserializedJob);
400    //        service.UpdateJobData(job, jobData);
401    //        Debug.WriteLine("finished calculating");
402    //      }
403    //    }
404    //  }
405    //  catch (Exception e) {
406    //    Assert.Fail(e.Message, e);
407    //  }
408    //}
409  }
410}
Note: See TracBrowser for help on using the repository browser.