Free cookie consent management tool by TermsFeed Policy Generator

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

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

#1233

  • updated jobstates documentation
  • enhanced ganttChart
  • fixed setting of jobstates
  • added option to force lifecycle-trigger (mainly for testing purposes)
File size: 16.0 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      PluginLoader.pluginAssemblies.Any();
40      ServiceLocator.Instance = new MockServiceLocator(ServiceLocator.Instance);
41    }
42
43    private IHiveService GetLocalService() {
44      return new HiveService();
45    }
46
47    [TestMethod]
48    public void TestJobs() {
49      var service = GetLocalService();
50
51      // create hive experiment
52      DT.HiveExperiment experiment = new DT.HiveExperiment() {
53        Name = "TestExperiment",
54        Description = ""
55      };
56
57      // create job
58      DT.Job job = new DT.Job() {
59        CoresNeeded = 1,
60        MemoryNeeded = 0,
61        Priority = 0
62      };
63      job.State = JobState.Offline;
64      job.StateLog.Add(new StateLog { State = JobState.Offline, DateTime = DateTime.Now });
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      // slave is responsible for updating state to 'Calculating'
139      service.UpdateJobState(jobLoaded.Id, JobState.Calculating, slave.Id, null, null);
140
141      // send progress
142      var progress = new Dictionary<Guid, TimeSpan>();
143      progress.Add(job.Id, new TimeSpan(1, 5, 10, 20, 30));
144      actions = service.Heartbeat(new Heartbeat() { SlaveId = slave.Id, AssignJob = true, FreeCores = 3, FreeMemory = 1024, JobProgress = progress });
145      Assert.AreEqual(0, actions.Count);
146
147      // the job should be in state 'Calculating' now
148      jobLoaded = service.GetJob(job.Id);
149      Assert.AreEqual(JobState.Calculating, jobLoaded.State);
150      Assert.AreEqual(new TimeSpan(1, 5, 10, 20, 30), jobLoaded.ExecutionTime.Value);
151
152      // delete
153      service.DeleteHiveExperiment(experiment.Id);
154      Assert.AreEqual(null, service.GetHiveExperiment(experiment.Id));
155      Assert.AreEqual(null, service.GetJob(job.Id));
156      Assert.AreEqual(null, service.GetJobData(job.Id));
157
158      // send another heartbeat with the deleted job; the server should command the abortion of the job
159      actions = service.Heartbeat(new Heartbeat() { SlaveId = slave.Id, AssignJob = true, FreeCores = 3, FreeMemory = 1024, JobProgress = progress });
160      Assert.AreEqual(1, actions.Count);
161      Assert.AreEqual(MessageContainer.MessageType.AbortJob, actions[0].Message);
162      Assert.AreEqual(job.Id, actions[0].JobId);
163
164      // delete slave
165      service.DeleteSlave(slave.Id);
166    }
167
168    List<DT.Job> jobs = new List<DT.Job>();
169
170
171    [TestMethod]
172    public void TestParentJobs() {
173      var service = GetLocalService();
174
175      // create hive experiment
176      DT.HiveExperiment experiment = new DT.HiveExperiment() {
177        Name = "TestExperiment",
178        Description = ""
179      };
180
181      // create parent job
182      DT.Job parentJob = new DT.Job() {
183        CoresNeeded = 1,
184        MemoryNeeded = 0,
185        Priority = 0,
186        IsParentJob = true,
187        FinishWhenChildJobsFinished = true
188      };
189      parentJob.State = JobState.Offline;
190      parentJob.StateLog.Add(new StateLog { State = JobState.Offline, DateTime = DateTime.Now });
191
192      DT.JobData parentJobData = new DT.JobData() { Data = new byte[0] };
193
194      // create child job
195      DT.Job childJob = new DT.Job() {
196        CoresNeeded = 1,
197        MemoryNeeded = 0,
198        Priority = 0
199      };
200      childJob.State = JobState.Offline;
201      childJob.StateLog.Add(new StateLog { State = JobState.Offline, DateTime = DateTime.Now });
202
203      DT.JobData childJobData = new DT.JobData() { Data = new byte[1000] };
204
205      // create slave
206      DT.Slave slave = new Slave();
207      slave.Id = Guid.NewGuid();
208      slave.Name = "TestSlave";
209      slave.Memory = 1024;
210      slave.Cores = 4;
211      slave.CpuSpeed = 2800;
212      slave.OperatingSystem = "Windows 3.11";
213      slave.CpuArchitecture = CpuArchitecture.x64;
214
215      // add slave
216      service.AddSlave(slave);
217
218      // add parent job
219      parentJob.Id = service.AddJob(parentJob, parentJobData, new List<Guid> { slave.Id });
220      experiment.RootJobId = parentJob.Id;
221
222      // add child job
223      childJob.Id = service.AddChildJob(parentJob.Id, childJob, childJobData);
224      childJob.ParentJobId = parentJob.Id;
225
226      // add hive experiment
227      experiment.Id = service.AddHiveExperiment(experiment);
228
229      // test child job
230      var childJobLoaded = service.GetJob(childJob.Id);
231      Assert.AreEqual(childJob.ParentJobId, childJobLoaded.ParentJobId);
232      Assert.AreEqual(JobState.Waiting, childJobLoaded.State);
233      Assert.AreEqual(false, childJobLoaded.FinishWhenChildJobsFinished);
234      Assert.AreEqual(false, childJobLoaded.IsParentJob);
235
236      // test parent job
237      var parentJobLoaded = service.GetJob(parentJob.Id);
238      Assert.AreEqual(JobState.Waiting, parentJobLoaded.State);
239      Assert.AreEqual(true, parentJobLoaded.FinishWhenChildJobsFinished);
240      Assert.AreEqual(true, parentJobLoaded.IsParentJob);
241
242      // test heartbeat
243      var actions = service.Heartbeat(new Heartbeat() { SlaveId = slave.Id, AssignJob = true, FreeCores = 4, FreeMemory = 1024, JobProgress = new Dictionary<Guid, TimeSpan>() });
244      Assert.AreEqual(1, actions.Count); // only the child job should be assigned
245      Assert.AreEqual(MessageContainer.MessageType.CalculateJob, actions[0].Message);
246      Assert.AreEqual(childJob.Id, actions[0].JobId);
247
248      // lifecycle - let it process one server-heartbeat; the parent job must NOT be set to finished
249      service.TriggerLifecycle(true);
250
251      parentJobLoaded = service.GetJob(parentJob.Id);
252      Assert.AreEqual(JobState.Waiting, parentJobLoaded.State);
253
254      // set child job to finished
255      childJobLoaded = service.UpdateJobState(childJobLoaded.Id, JobState.Finished, slave.Id, null, null);
256
257      // lifecycle - let it process one server-heartbeat; this should set the parent job to finished
258      service.TriggerLifecycle(true);
259
260      // test if parent job is finished
261      parentJobLoaded = service.GetJob(parentJob.Id);
262      Assert.AreEqual(JobState.Finished, parentJobLoaded.State);
263
264      // delete experiment
265      service.DeleteHiveExperiment(experiment.Id);
266      Assert.AreEqual(null, service.GetJob(parentJob.Id));
267      Assert.AreEqual(null, service.GetJob(childJob.Id));
268
269      service.DeleteSlave(slave.Id);
270    }
271
272    //[TestMethod]
273    //public void TestHeartbeats() {
274    //  var service = GetLocalService();
275    //  // check if group already exists and delete
276    //  var existingSlaveGroup = service.GetSlaveGroups().SingleOrDefault(g => g.Name == "TestGroup");
277    //  if (existingSlaveGroup != null) {
278    //    var slavesToDelete = service.GetSlaves().Where(s => s.ParentResourceId == existingSlaveGroup.Id);
279    //    foreach (var slave in slavesToDelete) service.DeleteSlave(slave.Id);
280    //    service.DeleteSlaveGroup(existingSlaveGroup.Id);
281    //  }
282
283    //  Guid groupId = service.AddSlaveGroup(new SlaveGroup() { Name = "TestGroup", Description = "Used for unit tests" });
284
285    //  // create slaves
286    //  var slaves = new List<DT.Slave>();
287    //  for (int i = 0; i < 1; i++) {
288    //    DT.Slave slave = new DT.Slave() {
289    //      Cores = 2,
290    //      Memory = 4096,
291    //      Name = "Slave " + i,
292    //      IsAllowedToCalculate = true,
293    //      SlaveState = SlaveState.Idle,
294    //      CpuSpeed = 2800,
295    //      FreeCores = 2,
296    //      FreeMemory = 3000
297    //    };
298    //    // check if slave with this name already exists and delete
299    //    var existingSlave = service.GetSlaves().Where(s => s.Name == slave.Name).SingleOrDefault();
300    //    if (existingSlave != null) service.DeleteSlave(existingSlave.Id);
301
302    //    slave.Id = service.AddSlave(slave);
303    //    service.AddResourceToGroup(groupId, slave.Id);
304    //    slaves.Add(slave);
305    //  }
306
307    //  // create jobs with different group, they should not be assigned
308    //  existingSlaveGroup = service.GetSlaveGroups().SingleOrDefault(g => g.Name == "DummyGroup");
309    //  if (existingSlaveGroup != null) service.DeleteSlaveGroup(existingSlaveGroup.Id);
310
311    //  Guid dummyGroupId = service.AddSlaveGroup(new SlaveGroup() { Name = "DummyGroup", Description = "Used for unit tests; jobs from this group shall not be calculated" });
312    //  // create dummy jobs
313    //  var dummyJobs = new List<Job>();
314    //  for (int i = 0; i < 2; i++) {
315    //    Job job = new Job() {
316    //      CoresNeeded = 1, MemoryNeeded = 0
317    //    };
318    //    JobData jobData = new JobData() { Data = PersistenceUtil.Serialize(new MockJob(500, false)) };
319    //    job.Id = service.AddJob(job, jobData, new List<Guid> { dummyGroupId });
320    //    dummyJobs.Add(job);
321    //  }
322
323    //  // create jobs
324    //  for (int i = 0; i < 2; i++) {
325    //    Job job = new Job() {
326    //      CoresNeeded = 1, MemoryNeeded = 0
327    //    };
328    //    JobData jobData = new JobData() { Data = PersistenceUtil.Serialize(new MockJob(500, false)) };
329    //    job.Id = service.AddJob(job, jobData, new List<Guid> { groupId });
330    //    jobs.Add(job);
331    //  }
332
333    //  // send heartbeats
334    //  foreach (var slave in slaves) {
335    //    new Thread(new ParameterizedThreadStart(RunSlaveThread)).Start(slave);
336    //  }
337
338    //  IEnumerable<LightweightJob> lightweightJobs;
339    //  do {
340    //    Thread.Sleep(500);
341    //    lightweightJobs = service.GetLightweightJobs(jobs.Select(x => x.Id));
342    //  } while (!lightweightJobs.All(x => x.State == JobState.Finished));
343
344    //  // delete slaves
345    //  foreach (var slave in slaves) {
346    //    service.DeleteSlave(slave.Id);
347    //    Assert.AreEqual(null, service.GetSlave(slave.Id));
348    //  }
349
350    //  // delete groups
351    //  service.DeleteSlaveGroup(groupId);
352    //  service.DeleteSlaveGroup(dummyGroupId);
353
354    //  // delete jobs
355    //  foreach (var job in jobs) {
356    //    service.DeleteJob(job.Id);
357    //  }
358
359    //  // delete dummy jobs
360    //  foreach (var job in dummyJobs) {
361    //    service.DeleteJob(job.Id);
362    //  }
363    //}
364
365    //public void RunSlaveThread(object slaveobj) {
366    //  try {
367    //    var service = GetLocalService();
368    //    Slave slave = (Slave)slaveobj;
369    //    int freeCores = slave.Cores.Value;
370
371    //    for (int i = 0; i < 10; i++) {
372
373    //      var messages = service.Heartbeat(new Heartbeat() { SlaveId = slave.Id, FreeMemory = 2423, FreeCores = freeCores, JobProgress = new Dictionary<Guid, TimeSpan>() });
374    //      if (messages.Count == 0) {
375    //        Debug.WriteLine("No job available");
376    //        return; // no more jobs
377    //      }
378
379    //      Debug.WriteLine("Messages: {0}", string.Join(", ", messages.Select(m => m.Message)));
380
381    //      Assert.IsTrue(messages.Where(x => x.Message == MessageContainer.MessageType.AbortJob).Count() == 0);
382    //      Assert.IsTrue(messages.Where(x => x.Message == MessageContainer.MessageType.SayHello).Count() == 0);
383    //      Assert.IsTrue(messages.Where(x => x.Message == MessageContainer.MessageType.PauseJob).Count() == 0);
384
385    //      var calculateJobMessage = messages.Where(x => x.Message == MessageContainer.MessageType.CalculateJob).SingleOrDefault();
386    //      if (calculateJobMessage != null) {
387    //        if (!jobs.Select(j => j.Id).Contains(calculateJobMessage.JobId))
388    //          Assert.Fail("Got job which was not assigned to the slavegroup");
389
390    //        Debug.WriteLine("Job available, calculating");
391    //        Job job = service.GetJob(calculateJobMessage.JobId);
392
393    //        JobData jobData = service.GetJobData(job.Id);
394    //        IJob deserializedJob = PersistenceUtil.Deserialize<IJob>(jobData.Data);
395    //        deserializedJob.Start();
396    //        job.SetState(JobState.Finished);
397    //        jobs.Where(x => x.Id == job.Id).Single().SetState(JobState.Finished);
398    //        jobData.Data = PersistenceUtil.Serialize(deserializedJob);
399    //        service.UpdateJobData(job, jobData);
400    //        Debug.WriteLine("finished calculating");
401    //      }
402    //    }
403    //  }
404    //  catch (Exception e) {
405    //    Assert.Fail(e.Message, e);
406    //  }
407    //}
408  }
409}
Note: See TracBrowser for help on using the repository browser.