Free cookie consent management tool by TermsFeed Policy Generator

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

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

#1233

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