AlgorithmProxyTest.h 8.73 KB
Newer Older
1
2
3
// Mantid Repository : https://github.com/mantidproject/mantid
//
// Copyright © 2018 ISIS Rutherford Appleton Laboratory UKRI,
4
5
//   NScD Oak Ridge National Laboratory, European Spallation Source,
//   Institut Laue - Langevin & CSNS, Institute of High Energy Physics, CAS
6
// SPDX - License - Identifier: GPL - 3.0 +
7
#pragma once
8
9
10

#include <cxxtest/TestSuite.h>

11
#include "MantidAPI/Algorithm.h"
LamarMoore's avatar
LamarMoore committed
12
#include "MantidAPI/AlgorithmManager.h"
13
#include "MantidAPI/AlgorithmObserver.h"
LamarMoore's avatar
LamarMoore committed
14
#include "MantidAPI/AlgorithmProxy.h"
15

16
17
#include <Poco/ActiveResult.h>
#include <Poco/Thread.h>
18

19
#include <boost/lexical_cast.hpp>
David Fairbrother's avatar
David Fairbrother committed
20
#include <utility>
21

22
23
24
using namespace Mantid::API;
using namespace Mantid::Kernel;

25
class ToyAlgorithmProxy : public Algorithm {
26
27
public:
  ToyAlgorithmProxy() : Algorithm() {}
28
29
  ~ToyAlgorithmProxy() override {}
  const std::string name() const override {
30
    return "ToyAlgorithmProxy";
Hahn, Steven's avatar
Hahn, Steven committed
31
  } ///< Algorithm's name for identification
32
33
34
35
  int version() const override {
    return 1;
  } ///< Algorithm's version for identification
  const std::string category() const override {
36
37
    return "ProxyCat";
  } ///< Algorithm's category for identification
38
  const std::vector<std::string> seeAlso() const override {
Nick Draper's avatar
Nick Draper committed
39
    return {"elephant", "seal"};
40
  } ///< Algorithm's seeAlso
41
42
43
44
45
46
47
48
  const std::string alias() const override {
    return "Dog";
  } ///< Algorithm's alias
  const std::string summary() const override { return "Test summary"; }
  const std::string workspaceMethodName() const override {
    return "toyalgorithm";
  }
  const std::string workspaceMethodOnTypes() const override {
49
    return "MatrixWorkspace;ITableWorkspace";
50
  }
51
  const std::string workspaceMethodInputProperty() const override {
52
53
54
    return "InputWorkspace";
  }

55
  void init() override {
56
57
58
59
    declareProperty("prop1", "value");
    declareProperty("prop2", 1);
    declareProperty("out", 8, Direction::Output);
  }
60
  void exec() override {
61
62
63
64
65
66
67
68
69
70
71
72
73
    std::string p1 = getProperty("prop1");
    int p2 = getProperty("prop2");

    Poco::Thread::current()->sleep(500);
    progress(0.333, "Running");
    interruption_point();
    Algorithm *alg = dynamic_cast<Algorithm *>(this);
    TS_ASSERT(alg);

    TS_ASSERT_EQUALS(p1, "stuff");
    TS_ASSERT_EQUALS(p2, 17);

    setProperty("out", 28);
74
75
76
  }
};

77
class ToyAlgorithmProxyMultipleCategory : public Algorithm {
Nick Draper's avatar
Nick Draper committed
78
79
public:
  ToyAlgorithmProxyMultipleCategory() : Algorithm() {}
80
81
  ~ToyAlgorithmProxyMultipleCategory() override {}
  const std::string name() const override {
82
    return "ToyAlgorithmProxyMultipleCategory";
Hahn, Steven's avatar
Hahn, Steven committed
83
  } ///< Algorithm's name for identification
84
85
86
87
  int version() const override {
    return 1;
  } ///< Algorithm's version for identification
  const std::string category() const override {
88
89
    return "ProxyCat;ProxyLeopard";
  } ///< Algorithm's category for identification
90
91
92
93
94
  const std::string alias() const override {
    return "Dog";
  } ///< Algorithm's alias
  const std::string summary() const override { return "Test summary"; }
  void init() override {
95
96
97
    declareProperty("prop1", "value");
    declareProperty("prop2", 1);
    declareProperty("out", 8, Direction::Output);
Nick Draper's avatar
Nick Draper committed
98
  }
99
  void exec() override {
100
101
102
103
104
105
106
107
108
109
110
111
112
    std::string p1 = getProperty("prop1");
    int p2 = getProperty("prop2");

    Poco::Thread::current()->sleep(500);
    progress(0.333, "Running");
    interruption_point();
    Algorithm *alg = dynamic_cast<Algorithm *>(this);
    TS_ASSERT(alg);

    TS_ASSERT_EQUALS(p1, "stuff");
    TS_ASSERT_EQUALS(p2, 17);

    setProperty("out", 28);
Nick Draper's avatar
Nick Draper committed
113
114
115
  }
};

116
DECLARE_ALGORITHM(ToyAlgorithmProxy)
Nick Draper's avatar
Nick Draper committed
117
DECLARE_ALGORITHM(ToyAlgorithmProxyMultipleCategory)
118

119
class TestProxyObserver : public AlgorithmObserver {
120
public:
121
122
123
124
  bool start, progress, finish;
  TestProxyObserver()
      : AlgorithmObserver(), start(false), progress(false), finish(false) {}
  TestProxyObserver(IAlgorithm_const_sptr alg)
David Fairbrother's avatar
David Fairbrother committed
125
126
      : AlgorithmObserver(std::move(alg)), start(false), progress(false),
        finish(false) {}
127
128
129
  void startHandle(const IAlgorithm *) override { start = true; }
  void progressHandle(const IAlgorithm *, double p,
                      const std::string &msg) override {
130
131
132
133
    progress = true;
    TS_ASSERT_EQUALS(p, 0.333);
    TS_ASSERT_EQUALS(msg, "Running");
  }
134
  void finishHandle(const IAlgorithm *) override { finish = true; }
135
136
};

137
class AlgorithmProxyTest : public CxxTest::TestSuite {
138
public:
139
140
141
142
143
144
145
146
  void testCreateProxy() {
    IAlgorithm_sptr alg =
        AlgorithmManager::Instance().create("ToyAlgorithmProxy");
    TS_ASSERT(dynamic_cast<AlgorithmProxy *>(alg.get()));
    TS_ASSERT_EQUALS(alg->name(), "ToyAlgorithmProxy");
    TS_ASSERT_EQUALS(alg->version(), 1);
    TS_ASSERT_EQUALS(alg->category(), "ProxyCat");
    TS_ASSERT_EQUALS(alg->alias(), "Dog");
Nick Draper's avatar
Nick Draper committed
147
    std::vector<std::string> seeAlsoList{"elephant", "seal"};
148
    TS_ASSERT_EQUALS(alg->seeAlso(), seeAlsoList);
149
150
151
152
153
154
155
156
    TS_ASSERT(alg->isInitialized());
    TS_ASSERT(alg->existsProperty("prop1"));
    TS_ASSERT(alg->existsProperty("prop2"));
    TS_ASSERT(!alg->isRunning());
    alg->setProperty("prop1", "stuff");
    alg->setProperty("prop2", 17);
    TS_ASSERT_THROWS_NOTHING(alg->execute());
    TS_ASSERT(alg->isExecuted());
157
158
    TS_ASSERT_EQUALS(ExecutionState::Finished, alg->executionState());
    TS_ASSERT_EQUALS(ResultState::Success, alg->resultState());
159
160
161
    int out = alg->getProperty("out");
    TS_ASSERT_EQUALS(out, 28);
  }
Nick Draper's avatar
Nick Draper committed
162

163
164
165
166
167
168
169
  void testMultipleCategory() {
    IAlgorithm_sptr alg = AlgorithmManager::Instance().create(
        "ToyAlgorithmProxyMultipleCategory");
    TS_ASSERT(dynamic_cast<AlgorithmProxy *>(alg.get()));
    TS_ASSERT_EQUALS(alg->name(), "ToyAlgorithmProxyMultipleCategory");
    TS_ASSERT_EQUALS(alg->version(), 1);
    TS_ASSERT_EQUALS(alg->category(), "ProxyCat;ProxyLeopard");
170
    std::vector<std::string> result{"ProxyCat", "ProxyLeopard"};
171
172
173
174
    TS_ASSERT_EQUALS(alg->categories(), result);
    TS_ASSERT_EQUALS(alg->alias(), "Dog");
    TS_ASSERT(alg->isInitialized());
  }
Nick Draper's avatar
Nick Draper committed
175

176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
  /**
   * Disabled due to random failures that cannot be pinned down and are most
   * likely timing issues.
   * This test has never failed legitimately and only serves to cause confusion
   * when it fails
   * due to completely unrelated changes.
   */
  void xtestRunning() {
    IAlgorithm_sptr alg =
        AlgorithmManager::Instance().create("ToyAlgorithmProxy");
    TS_ASSERT(dynamic_cast<AlgorithmProxy *>(alg.get()));
    alg->setProperty("prop1", "stuff");
    alg->setProperty("prop2", 17);
    Poco::ActiveResult<bool> res = alg->executeAsync();
    res.tryWait(60);
    TS_ASSERT(alg->isRunning());

    res.wait();
    TS_ASSERT(res.data());
    TS_ASSERT(alg->isExecuted());
  }
197

198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
  void testCancel() {
    IAlgorithm_sptr alg =
        AlgorithmManager::Instance().create("ToyAlgorithmProxy");
    TS_ASSERT(dynamic_cast<AlgorithmProxy *>(alg.get()));
    alg->setProperty("prop1", "stuff");
    alg->setProperty("prop2", 17);
    Poco::ActiveResult<bool> res = alg->executeAsync();
    res.tryWait(100);
    alg->cancel();
    res.wait();
    TS_ASSERT(!alg->isExecuted());
    int out = alg->getProperty("out");
    TS_ASSERT_EQUALS(out, 8);
  }
  void testAddObserver() {
    IAlgorithm_sptr alg =
        AlgorithmManager::Instance().create("ToyAlgorithmProxy");
    TS_ASSERT(dynamic_cast<AlgorithmProxy *>(alg.get()));
    alg->setProperty("prop1", "stuff");
    alg->setProperty("prop2", 17);
    TestProxyObserver obs(alg);
    Poco::ActiveResult<bool> res = alg->executeAsync();
    res.wait();
    TS_ASSERT(obs.start);
    TS_ASSERT(obs.progress);
    TS_ASSERT(obs.finish);
  }
225

226
227
228
  void test_WorkspaceMethodFunctionsReturnProxiedContent() {
    IAlgorithm_sptr alg =
        AlgorithmManager::Instance().create("ToyAlgorithmProxy");
229

230
231
232
233
234
235
236
237
238
239
    TS_ASSERT_EQUALS("toyalgorithm", alg->workspaceMethodName());

    auto types = alg->workspaceMethodOn();
    TS_ASSERT_EQUALS(2, types.size());
    if (types.size() == 2) {
      TS_ASSERT_EQUALS("MatrixWorkspace", types[0]);
      TS_ASSERT_EQUALS("ITableWorkspace", types[1]);
    }
    TS_ASSERT_EQUALS("InputWorkspace", alg->workspaceMethodInputProperty());
  }
240
241

  void test_copyPropertiesFrom() {
Nick Draper's avatar
Nick Draper committed
242
    IAlgorithm_sptr alg =
243
        AlgorithmManager::Instance().create("ToyAlgorithmProxy");
Nick Draper's avatar
Nick Draper committed
244
245
246
247
    alg->initialize();
    alg->setPropertyValue("prop1", "string");
    alg->setPropertyValue("prop2", "1");
    IAlgorithm_sptr algCopy =
248
249
        AlgorithmManager::Instance().create("ToyAlgorithmProxy");

Nick Draper's avatar
Nick Draper committed
250
251
252
    auto algProxy = boost::dynamic_pointer_cast<AlgorithmProxy>(alg);
    auto algCopyProxy = boost::dynamic_pointer_cast<AlgorithmProxy>(algCopy);
    algCopyProxy->copyPropertiesFrom(*algProxy);
253

Nick Draper's avatar
Nick Draper committed
254
    int val = boost::lexical_cast<int>(algCopy->getPropertyValue("prop2"));
255

Nick Draper's avatar
Nick Draper committed
256
    TS_ASSERT_EQUALS(val, 1);
257

Nick Draper's avatar
Nick Draper committed
258
259
260
    // set another value and check the other value is unaffected
    algCopy->setPropertyValue("prop1", "A difference");
    int val2 = boost::lexical_cast<int>(algCopy->getPropertyValue("prop2"));
261

Nick Draper's avatar
Nick Draper committed
262
    TS_ASSERT_EQUALS(val, val2);
263
  }
264
};