Free cookie consent management tool by TermsFeed Policy Generator

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

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

#1233

  • changed the workflow of aquireing a new job from server.
    • if a job is available for calculation, the slave receives the jobId already with the heartbeats. The job is then exclusively assigned to this slave.
  • extended the metainfo for a slave by OperatingSystem and CpuArchitecture
  • enhanced the way plugin-dependencies are discovered by using the types used by XmlGenerator. Now only mimimum amount of plugins are transferred.
  • selection of waiting jobs now consideres assigned slave-group
  • more unit tests for service
  • added unit tests for experiment manager
File size: 9.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.Clients.Hive;
26using HeuristicLab.Clients.Hive.Slave.Tests;
27using HeuristicLab.Services.Hive.Common.DataTransfer;
28using HeuristicLab.Services.Hive.Common.ServiceContracts;
29using Microsoft.VisualStudio.TestTools.UnitTesting;
30using System.Threading;
31using HeuristicLab.Hive;
32using HeuristicLab.Services.Hive.Common;
33
34namespace HeuristicLab.Services.Hive.Tests {
35
36  using DT = HeuristicLab.Services.Hive.Common.DataTransfer;
37  using System.Diagnostics;
38
39  [TestClass]
40  public class ServiceTests {
41
42    [ClassInitialize]
43    public static void MyClassInitialize(TestContext testContext) {
44      PluginLoader.pluginAssemblies.Any();
45      ServiceLocator.Instance = new MockServiceLocator(ServiceLocator.Instance);
46    }
47
48    private IHiveService GetLocalService() {
49      return new HiveService();
50    }
51
52    [TestMethod]
53    public void TestJobs() {
54      var service = GetLocalService();
55
56      DT.HiveExperiment experiment = new DT.HiveExperiment() {
57        Name = "TestExperiment",
58        Description = ""
59      };
60
61      DT.Job job = new DT.Job() {
62        CoresNeeded = 1,
63        MemoryNeeded = 0,
64        Priority = 0
65      };
66
67      DT.JobData jobData = new DT.JobData() {
68        Data = PersistenceUtil.Serialize(new MockJob(500, true))
69      };
70
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.PluginId = plugin1.Id;
80      pluginData1.FileName = "Tests.MyPlugin-1.0.dll";
81      pluginData1.Data = new byte[] { 0, 1, 2, 3, 4, 5 };
82
83      job.PluginsNeededIds.Add(plugin1.Id);
84
85      job.Id = service.AddJob(job, jobData, null);
86      experiment.RootJobId = job.Id;
87
88      DT.Job jobLoaded = service.GetJob(job.Id);
89      Assert.AreEqual(job.Id, jobLoaded.Id);
90      Assert.AreEqual(job.CoresNeeded, jobLoaded.CoresNeeded);
91      Assert.AreEqual(job.MemoryNeeded, jobLoaded.MemoryNeeded);
92      Assert.AreEqual(job.Priority, jobLoaded.Priority);
93      Assert.AreEqual(JobState.Waiting, jobLoaded.JobState);
94      Assert.AreEqual(ServiceLocator.Instance.AuthorizationManager.UserId, job.UserId);
95      Assert.IsTrue(job.PluginsNeededIds.SequenceEqual(jobLoaded.PluginsNeededIds));
96
97      DT.JobData jobDataLoaded = service.GetJobData(job.Id);
98      Assert.AreEqual(job.Id, jobDataLoaded.JobId);
99      Assert.IsTrue(jobData.Data.SequenceEqual(jobDataLoaded.Data));
100
101      experiment.Id = service.AddHiveExperiment(experiment);
102
103      DT.HiveExperiment experimentLoaded = service.GetHiveExperiment(experiment.Id);
104      Assert.AreEqual(experiment.Id, experimentLoaded.Id);
105      Assert.AreEqual(experiment.Name, experimentLoaded.Name);
106      Assert.AreEqual(experiment.Description, experimentLoaded.Description);
107      Assert.AreEqual(experiment.RootJobId, experimentLoaded.RootJobId);
108
109      service.DeleteHiveExperiment(experiment.Id);
110      Assert.AreEqual(null, service.GetHiveExperiment(experiment.Id));
111      Assert.AreEqual(null, service.GetJob(job.Id));
112      Assert.AreEqual(null, service.GetJobData(job.Id));
113    }
114
115    List<DT.Job> jobs = new List<DT.Job>();
116
117    [TestMethod]
118    public void TestHeartbeats() {
119      var service = GetLocalService();
120      // check if group already exists and delete
121      var existingSlaveGroup = service.GetSlaveGroups().SingleOrDefault(g => g.Name == "TestGroup");
122      if (existingSlaveGroup != null) {
123        var slavesToDelete = service.GetSlaves().Where(s => s.ParentResourceId == existingSlaveGroup.Id);
124        foreach (var slave in slavesToDelete) service.DeleteSlave(slave.Id);
125        service.DeleteSlaveGroup(existingSlaveGroup.Id);
126      }
127
128      Guid groupId = service.AddSlaveGroup(new SlaveGroup() { Name = "TestGroup", Description = "Used for unit tests" });
129
130      // create slaves
131      var slaves = new List<DT.Slave>();
132      for (int i = 0; i < 1; i++) {
133        DT.Slave slave = new DT.Slave() {
134          Cores = 2,
135          Memory = 4096,
136          Name = "Slave " + i,
137          IsAllowedToCalculate = true,
138          SlaveState = SlaveState.Idle,
139          CpuSpeed = 2800,
140          FreeCores = 2,
141          FreeMemory = 3000
142        };
143        // check if slave with this name already exists and delete
144        var existingSlave = service.GetSlaves().Where(s => s.Name == slave.Name).SingleOrDefault();
145        if (existingSlave != null) service.DeleteSlave(existingSlave.Id);
146
147        slave.Id = service.AddSlave(slave);
148        service.AddResourceToGroup(groupId, slave.Id);
149        slaves.Add(slave);
150      }
151
152      // create jobs with different group, they should not be assigned
153      existingSlaveGroup = service.GetSlaveGroups().SingleOrDefault(g => g.Name == "DummyGroup");
154      if (existingSlaveGroup != null) service.DeleteSlaveGroup(existingSlaveGroup.Id);
155
156      Guid dummyGroupId = service.AddSlaveGroup(new SlaveGroup() { Name = "DummyGroup", Description = "Used for unit tests; jobs from this group shall not be calculated" });
157      // create dummy jobs
158      var dummyJobs = new List<Job>();
159      for (int i = 0; i < 2; i++) {
160        Job job = new Job() {
161          CoresNeeded = 1, MemoryNeeded = 0
162        };
163        JobData jobData = new JobData() { Data = PersistenceUtil.Serialize(new MockJob(500, false)) };
164        job.Id = service.AddJob(job, jobData, new List<Guid> { dummyGroupId });
165        dummyJobs.Add(job);
166      }
167
168      // create jobs
169      for (int i = 0; i < 2; i++) {
170        Job job = new Job() {
171          CoresNeeded = 1, MemoryNeeded = 0
172        };
173        JobData jobData = new JobData() { Data = PersistenceUtil.Serialize(new MockJob(500, false)) };
174        job.Id = service.AddJob(job, jobData, new List<Guid> { groupId });
175        jobs.Add(job);
176      }
177
178      // send heartbeats
179      foreach (var slave in slaves) {
180        new Thread(new ParameterizedThreadStart(RunSlaveThread)).Start(slave);
181      }
182
183      IEnumerable<LightweightJob> lightweightJobs;
184      do {
185        Thread.Sleep(500);
186        lightweightJobs = service.GetLightweightJobs(jobs.Select(x => x.Id));
187      } while (!lightweightJobs.All(x => x.JobState == JobState.Finished));
188
189      // delete slaves
190      foreach (var slave in slaves) {
191        service.DeleteSlave(slave.Id);
192        Assert.AreEqual(null, service.GetSlave(slave.Id));
193      }
194
195      // delete groups
196      service.DeleteSlaveGroup(groupId);
197      service.DeleteSlaveGroup(dummyGroupId);
198
199      // delete jobs
200      foreach (var job in jobs) {
201        service.DeleteJob(job.Id);
202      }
203
204      // delete dummy jobs
205      foreach (var job in dummyJobs) {
206        service.DeleteJob(job.Id);
207      }
208    }
209
210    public void RunSlaveThread(object slaveobj) {
211      try {
212        var service = GetLocalService();
213        Slave slave = (Slave)slaveobj;
214        int freeCores = slave.Cores.Value;
215
216        for (int i = 0; i < 10; i++) {
217
218          var messages = service.Heartbeat(new Heartbeat() { SlaveId = slave.Id, FreeMemory = 2423, FreeCores = freeCores, JobProgress = new Dictionary<Guid, TimeSpan>() });
219          if (messages.Count == 0) {
220            Debug.WriteLine("No job available");
221            return; // no more jobs
222          }
223
224          Debug.WriteLine("Messages: {0}", string.Join(", ", messages.Select(m => m.Message)));
225
226          Assert.IsTrue(messages.Where(x => x.Message == MessageContainer.MessageType.AbortJob).Count() == 0);
227          Assert.IsTrue(messages.Where(x => x.Message == MessageContainer.MessageType.SayHello).Count() == 0);
228          Assert.IsTrue(messages.Where(x => x.Message == MessageContainer.MessageType.PauseJob).Count() == 0);
229
230          var calculateJobMessage = messages.Where(x => x.Message == MessageContainer.MessageType.CalculateJob).SingleOrDefault();
231          if (calculateJobMessage != null) {
232            if (!jobs.Select(j => j.Id).Contains(calculateJobMessage.JobId))
233              Assert.Fail("Got job which was not assigned to the slavegroup");
234
235            Debug.WriteLine("Job available, calculating");
236            Job job = service.GetJob(calculateJobMessage.JobId);
237
238            JobData jobData = service.GetJobData(job.Id);
239            IJob deserializedJob = PersistenceUtil.Deserialize<IJob>(jobData.Data);
240            deserializedJob.Start();
241            job.JobState = JobState.Finished;
242            jobs.Where(x => x.Id == job.Id).Single().JobState = JobState.Finished;
243            jobData.Data = PersistenceUtil.Serialize(deserializedJob);
244            service.UpdateJob(job, jobData);
245            Debug.WriteLine("finished calculating");
246          }
247        }
248      }
249      catch (Exception e) {
250        Assert.Fail(e.Message, e);
251      }
252    }
253  }
254}
Note: See TracBrowser for help on using the repository browser.