Commit aa828bf83b4034ed875af93d5ca9a338bc4ef13a

Authored by Jojo-1000
Committed by Moritz Wirger
1 parent 710ee59b

Implement a shared-state cache model.

All resources on the bridge internally use the same json state.
Advantages: Different resources are always consistent.
Disadvantages: Different objects are no longer thread safe, changes are not transparent.
include/hueplusplus/BaseDevice.h
... ... @@ -120,6 +120,7 @@ public:
120 120 virtual void refresh(bool force = false);
121 121  
122 122 protected:
  123 + BaseDevice(int id, const std::shared_ptr<APICache>& baseCache);
123 124 //! \brief Protected ctor that is used by subclasses.
124 125 //!
125 126 //! \param id Integer that specifies the id of this device
... ...
include/hueplusplus/Bridge.h
... ... @@ -145,9 +145,11 @@ public:
145 145 //! the bridge. Can be left empty and acquired in \ref requestUsername.
146 146 //! \param handler HttpHandler for communication with the bridge
147 147 //! \param refreshDuration Time between refreshing the cached state.
  148 + //! \param sharedState Uses a single, shared cache for all objects on the bridge.
148 149 Bridge(const std::string& ip, const int port, const std::string& username,
149 150 std::shared_ptr<const IHttpHandler> handler,
150   - std::chrono::steady_clock::duration refreshDuration = std::chrono::seconds(10));
  151 + std::chrono::steady_clock::duration refreshDuration = std::chrono::seconds(10),
  152 + bool sharedState = false);
151 153  
152 154 //! \brief Refreshes the bridge state.
153 155 //!
... ... @@ -265,6 +267,7 @@ private:
265 267 detail::MakeCopyable<SensorList> sensorList;
266 268 detail::MakeCopyable<RuleList> ruleList;
267 269 detail::MakeCopyable<BridgeConfig> bridgeConfig;
  270 + bool sharedState;
268 271 };
269 272 } // namespace hueplusplus
270 273  
... ...
include/hueplusplus/Group.h
... ... @@ -41,6 +41,7 @@ namespace hueplusplus
41 41 class Group
42 42 {
43 43 public:
  44 + Group(int id, const std::shared_ptr<APICache>& baseCache);
44 45 //! \brief Creates group with id
45 46 //! \param id Group id in the bridge
46 47 //! \param commands HueCommandAPI for requests
... ...
include/hueplusplus/HueDeviceTypes.h
... ... @@ -46,7 +46,7 @@ public:
46 46 //! \throws HueException when light type is unknown
47 47 //! \throws HueAPIResponseException when response contains an error
48 48 //! \throws nlohmann::json::parse_error when response could not be parsed
49   - Light createLight(const nlohmann::json& lightState, int id);
  49 + Light createLight(const nlohmann::json& lightState, int id, const std::shared_ptr<APICache>& baseCache = {});
50 50  
51 51 private:
52 52 //! \brief Get color type from light JSON.
... ...
include/hueplusplus/Light.h
... ... @@ -554,6 +554,7 @@ public:
554 554 ///@}
555 555  
556 556 protected:
  557 +
557 558 //! \brief Protected ctor that is used by \ref Bridge class.
558 559 //!
559 560 //! \param id Integer that specifies the id of this light
... ... @@ -562,6 +563,9 @@ protected:
562 563 //! leaves strategies unset
563 564 Light(int id, const HueCommandAPI& commands);
564 565  
  566 +
  567 + Light(int id, const std::shared_ptr<APICache>& baseCache);
  568 +
565 569 //! \brief Protected ctor that is used by \ref Bridge class, also sets
566 570 //! strategies.
567 571 //!
... ...
include/hueplusplus/ResourceList.h
... ... @@ -45,6 +45,9 @@ template &lt;typename Resource, typename IdT&gt;
45 45 class ResourceList
46 46 {
47 47 public:
  48 + struct SharedStateTag
  49 + { };
  50 +
48 51 using ResourceType = Resource;
49 52 using IdType = IdT;
50 53 static_assert(std::is_integral<IdType>::value || std::is_same<std::string, IdType>::value,
... ... @@ -57,9 +60,13 @@ public:
57 60 //! \param factory Optional factory function to create Resources.
58 61 //! Necessary if Resource is not constructible as described above.
59 62 ResourceList(std::shared_ptr<APICache> baseCache, const std::string& cacheEntry,
60   - std::chrono::steady_clock::duration refreshDuration,
61   - const std::function<Resource(IdType, const nlohmann::json&)>& factory = nullptr)
62   - : stateCache(baseCache, cacheEntry, refreshDuration), factory(factory), path(stateCache.getRequestPath() + '/')
  63 + std::chrono::steady_clock::duration refreshDuration, bool sharedState = false,
  64 + const std::function<Resource(IdType, const nlohmann::json&, const std::shared_ptr<APICache>&)>& factory
  65 + = nullptr)
  66 + : stateCache(std::make_shared<APICache>(baseCache, cacheEntry, refreshDuration)),
  67 + factory(factory),
  68 + path(stateCache->getRequestPath() + '/'),
  69 + sharedState(sharedState)
63 70 { }
64 71 //! \brief Construct ResourceList with a separate cache and optional factory function
65 72 //! \param commands HueCommandAPI for requests
... ... @@ -69,8 +76,12 @@ public:
69 76 //! Necessary if Resource is not constructible as described above.
70 77 ResourceList(const HueCommandAPI& commands, const std::string& path,
71 78 std::chrono::steady_clock::duration refreshDuration,
72   - const std::function<Resource(IdType, const nlohmann::json&)>& factory = nullptr)
73   - : stateCache(path, commands, refreshDuration), factory(factory), path(path + '/')
  79 + const std::function<Resource(IdType, const nlohmann::json&, const std::shared_ptr<APICache>&)>& factory
  80 + = nullptr)
  81 + : stateCache(std::make_shared<APICache>(path, commands, refreshDuration)),
  82 + factory(factory),
  83 + path(path + '/'),
  84 + sharedState(false)
74 85 { }
75 86  
76 87 //! \brief Deleted copy constructor
... ... @@ -79,7 +90,7 @@ public:
79 90 ResourceList& operator=(const ResourceList&) = delete;
80 91  
81 92 //! \brief Refreshes internal state now
82   - void refresh() { stateCache.refresh(); }
  93 + void refresh() { stateCache->refresh(); }
83 94  
84 95 //! \brief Get all resources that exist
85 96 //! \returns A vector of references to every Resource
... ... @@ -89,7 +100,7 @@ public:
89 100 //! \throws nlohmann::json::parse_error when response could not be parsed
90 101 std::vector<std::reference_wrapper<Resource>> getAll()
91 102 {
92   - nlohmann::json state = stateCache.getValue();
  103 + nlohmann::json state = stateCache->getValue();
93 104 for (auto it = state.begin(); it != state.end(); ++it)
94 105 {
95 106 get(maybeStoi(it.key()));
... ... @@ -118,7 +129,7 @@ public:
118 129 pos->second.refresh(true);
119 130 return pos->second;
120 131 }
121   - const nlohmann::json& state = stateCache.getValue();
  132 + const nlohmann::json& state = stateCache->getValue();
122 133 std::string key = maybeToString(id);
123 134 if (!state.count(key))
124 135 {
... ... @@ -141,7 +152,7 @@ public:
141 152 {
142 153 return true;
143 154 }
144   - return stateCache.getValue().count(maybeToString(id)) != 0;
  155 + return stateCache->getValue().count(maybeToString(id)) != 0;
145 156 }
146 157  
147 158 //! \brief Checks whether resource with id exists
... ... @@ -156,7 +167,7 @@ public:
156 167 {
157 168 return true;
158 169 }
159   - return stateCache.getValue().count(maybeToString(id)) != 0;
  170 + return stateCache->getValue().count(maybeToString(id)) != 0;
160 171 }
161 172  
162 173 //! \brief Removes the resource
... ... @@ -171,7 +182,7 @@ public:
171 182 bool remove(const IdType& id)
172 183 {
173 184 std::string requestPath = path + maybeToString(id);
174   - nlohmann::json result = stateCache.getCommandAPI().DELETERequest(
  185 + nlohmann::json result = stateCache->getCommandAPI().DELETERequest(
175 186 requestPath, nlohmann::json::object(), FileInfo {__FILE__, __LINE__, __func__});
176 187 bool success = utils::safeGetMember(result, 0, "success") == requestPath + " deleted";
177 188 auto it = resources.find(id);
... ... @@ -208,11 +219,18 @@ private:
208 219 {
209 220 if (factory)
210 221 {
211   - return factory(id, state);
  222 + return factory(id, state, sharedState ? stateCache : std::shared_ptr<APICache>());
212 223 }
213 224 else
214 225 {
215   - return Resource(id, stateCache.getCommandAPI(), stateCache.getRefreshDuration());
  226 + if (sharedState)
  227 + {
  228 + return Resource(id, stateCache);
  229 + }
  230 + else
  231 + {
  232 + return Resource(id, stateCache->getCommandAPI(), stateCache->getRefreshDuration());
  233 + }
216 234 }
217 235 }
218 236 // Resource is not constructable
... ... @@ -223,7 +241,7 @@ private:
223 241 throw HueException(FileInfo {__FILE__, __LINE__, __func__},
224 242 "Resource is not constructable with default parameters, but no factory given");
225 243 }
226   - return factory(id, state);
  244 + return factory(id, state, sharedState ? stateCache : std::shared_ptr<APICache>());
227 245 }
228 246  
229 247 private:
... ... @@ -233,10 +251,11 @@ private:
233 251 static std::string maybeToString(const IdType& id, std::false_type) { return id; }
234 252  
235 253 protected:
236   - APICache stateCache;
237   - std::function<Resource(IdType, const nlohmann::json&)> factory;
  254 + std::shared_ptr<APICache> stateCache;
  255 + std::function<Resource(IdType, const nlohmann::json&, const std::shared_ptr<APICache>&)> factory;
238 256 std::string path;
239 257 std::map<IdType, Resource> resources;
  258 + bool sharedState;
240 259 };
241 260  
242 261 //! \brief Handles a ResourceList of physical devices which can be searched for
... ... @@ -258,12 +277,12 @@ public:
258 277 requestPath.pop_back();
259 278 if (deviceIds.empty())
260 279 {
261   - this->stateCache.getCommandAPI().POSTRequest(
  280 + this->stateCache->getCommandAPI().POSTRequest(
262 281 requestPath, nlohmann::json::object(), FileInfo {__FILE__, __LINE__, __func__});
263 282 }
264 283 else
265 284 {
266   - this->stateCache.getCommandAPI().POSTRequest(
  285 + this->stateCache->getCommandAPI().POSTRequest(
267 286 requestPath, nlohmann::json {{"deviceid", deviceIds}}, FileInfo {__FILE__, __LINE__, __func__});
268 287 }
269 288 }
... ... @@ -271,7 +290,7 @@ public:
271 290 //! \brief Get devices found in last search
272 291 NewDeviceList getNewDevices() const
273 292 {
274   - nlohmann::json response = this->stateCache.getCommandAPI().GETRequest(
  293 + nlohmann::json response = this->stateCache->getCommandAPI().GETRequest(
275 294 this->path + "new", nlohmann::json::object(), FileInfo {__FILE__, __LINE__, __func__});
276 295 return NewDeviceList::parse(response);
277 296 }
... ... @@ -306,7 +325,7 @@ public:
306 325 std::string requestPath = this->path;
307 326 // Remove slash
308 327 requestPath.pop_back();
309   - nlohmann::json response = this->stateCache.getCommandAPI().POSTRequest(
  328 + nlohmann::json response = this->stateCache->getCommandAPI().POSTRequest(
310 329 requestPath, params.getRequest(), FileInfo {__FILE__, __LINE__, __func__});
311 330 nlohmann::json id = utils::safeGetMember(response, 0, "success", "id");
312 331 if (id.is_string())
... ... @@ -316,7 +335,7 @@ public:
316 335 {
317 336 idStr.erase(0, this->path.size());
318 337 }
319   - this->stateCache.refresh();
  338 + this->stateCache->refresh();
320 339 return this->maybeStoi(idStr);
321 340 }
322 341 return typename BaseResourceList::IdType {};
... ... @@ -350,7 +369,7 @@ public:
350 369 pos->second.refresh();
351 370 return pos->second;
352 371 }
353   - const nlohmann::json& state = this->stateCache.getValue();
  372 + const nlohmann::json& state = this->stateCache->getValue();
354 373 std::string key = this->maybeToString(id);
355 374 if (!state.count(key) && id != 0)
356 375 {
... ...
include/hueplusplus/Sensor.h
... ... @@ -59,6 +59,8 @@ Alert alertFromString(const std::string&amp; s);
59 59 class Sensor : public BaseDevice
60 60 {
61 61 public:
  62 + Sensor(int id, const std::shared_ptr<APICache>& baseCache);
  63 +
62 64 //! \brief Construct Sensor.
63 65 //! \param id Integer that specifies the id of this sensor
64 66 //! \param commands HueCommandAPI for communication with the bridge
... ...
include/hueplusplus/SensorList.h
... ... @@ -58,7 +58,7 @@ public:
58 58 template <typename T>
59 59 std::vector<T> getAllByType()
60 60 {
61   - nlohmann::json state = this->stateCache.getValue();
  61 + nlohmann::json state = this->stateCache->getValue();
62 62 std::vector<T> result;
63 63 for (auto it = state.begin(); it != state.end(); ++it)
64 64 {
... ...
src/BaseDevice.cpp
... ... @@ -91,6 +91,10 @@ bool BaseDevice::setName(const std::string&amp; name)
91 91 return utils::safeGetMember(reply, 0, "success", "/lights/" + std::to_string(id) + "/name").is_string();
92 92 }
93 93  
  94 +BaseDevice::BaseDevice(int id, const std::shared_ptr<APICache>& baseCache)
  95 + : id(id), state(baseCache, std::to_string(id), baseCache->getRefreshDuration())
  96 +{ }
  97 +
94 98 BaseDevice::BaseDevice(
95 99 int id, const HueCommandAPI& commands, const std::string& path, std::chrono::steady_clock::duration refreshDuration)
96 100 : id(id), path(path), state(path + std::to_string(id), commands, refreshDuration)
... ...
src/Bridge.cpp
... ... @@ -138,7 +138,7 @@ std::string BridgeFinder::ParseDescription(const std::string&amp; description)
138 138 }
139 139  
140 140 Bridge::Bridge(const std::string& ip, const int port, const std::string& username,
141   - std::shared_ptr<const IHttpHandler> handler, std::chrono::steady_clock::duration refreshDuration)
  141 + std::shared_ptr<const IHttpHandler> handler, std::chrono::steady_clock::duration refreshDuration, bool sharedState)
142 142 : ip(ip),
143 143 username(username),
144 144 port(port),
... ... @@ -146,15 +146,18 @@ Bridge::Bridge(const std::string&amp; ip, const int port, const std::string&amp; usernam
146 146 refreshDuration(refreshDuration),
147 147 stateCache(std::make_shared<APICache>(
148 148 "", HueCommandAPI(ip, port, username, http_handler), std::chrono::steady_clock::duration::max())),
149   - lightList(stateCache, "lights", refreshDuration,
  149 + lightList(stateCache, "lights", refreshDuration, sharedState,
150 150 [factory = LightFactory(stateCache->getCommandAPI(), refreshDuration)](
151   - int id, const nlohmann::json& state) mutable { return factory.createLight(state, id); }),
152   - groupList(stateCache, "groups", refreshDuration),
153   - scheduleList(stateCache, "schedules", refreshDuration),
154   - sceneList(stateCache, "scenes", refreshDuration),
155   - sensorList(stateCache, "sensors", refreshDuration),
156   - ruleList(stateCache, "rules", refreshDuration),
157   - bridgeConfig(stateCache, refreshDuration)
  151 + int id, const nlohmann::json& state, const std::shared_ptr<APICache>& baseCache) mutable {
  152 + return factory.createLight(state, id, baseCache);
  153 + }),
  154 + groupList(stateCache, "groups", refreshDuration, sharedState),
  155 + scheduleList(stateCache, "schedules", refreshDuration, sharedState),
  156 + sceneList(stateCache, "scenes", refreshDuration, sharedState),
  157 + sensorList(stateCache, "sensors", refreshDuration, sharedState),
  158 + ruleList(stateCache, "rules", refreshDuration, sharedState),
  159 + bridgeConfig(stateCache, refreshDuration),
  160 + sharedState(sharedState)
158 161 { }
159 162  
160 163 void Bridge::refresh()
... ... @@ -304,13 +307,14 @@ void Bridge::setHttpHandler(std::shared_ptr&lt;const IHttpHandler&gt; handler)
304 307 {
305 308 http_handler = handler;
306 309 stateCache = std::make_shared<APICache>("", HueCommandAPI(ip, port, username, handler), refreshDuration);
307   - lightList = LightList(stateCache, "lights", refreshDuration,
308   - [factory = LightFactory(stateCache->getCommandAPI(), refreshDuration)](
309   - int id, const nlohmann::json& state) mutable { return factory.createLight(state, id); });
310   - groupList = GroupList(stateCache, "groups", refreshDuration);
311   - scheduleList = ScheduleList(stateCache, "schedules", refreshDuration);
312   - sceneList = SceneList(stateCache, "scenes", refreshDuration);
313   - sensorList = SensorList(stateCache, "sensors", refreshDuration);
  310 + lightList = LightList(stateCache, "lights", refreshDuration,sharedState,
  311 + [factory = LightFactory(stateCache->getCommandAPI(), refreshDuration)](int id, const nlohmann::json& state,
  312 + const std::shared_ptr<APICache>& baseCache) mutable { return factory.createLight(state, id, baseCache); });
  313 + groupList = GroupList(stateCache, "groups", refreshDuration, sharedState);
  314 + scheduleList = ScheduleList(stateCache, "schedules", refreshDuration, sharedState);
  315 + sceneList = SceneList(stateCache, "scenes", refreshDuration, sharedState);
  316 + sensorList = SensorList(stateCache, "sensors", refreshDuration, sharedState);
  317 + ruleList = RuleList(stateCache, "rules", refreshDuration, sharedState);
314 318 bridgeConfig = BridgeConfig(stateCache, refreshDuration);
315 319 stateCache->refresh();
316 320 }
... ...
src/Group.cpp
... ... @@ -4,6 +4,10 @@
4 4  
5 5 namespace hueplusplus
6 6 {
  7 +Group::Group(int id, const std::shared_ptr<APICache>& baseCache)
  8 + : id(id), state(baseCache, std::to_string(id), baseCache->getRefreshDuration())
  9 +{ }
  10 +
7 11 Group::Group(int id, const HueCommandAPI& commands, std::chrono::steady_clock::duration refreshDuration)
8 12 : id(id), state("/groups/" + std::to_string(id), commands, refreshDuration)
9 13 {
... ...
src/HueDeviceTypes.cpp
... ... @@ -67,41 +67,46 @@ LightFactory::LightFactory(const HueCommandAPI&amp; commands, std::chrono::steady_cl
67 67 extendedColorTemperature(std::make_shared<ExtendedColorTemperatureStrategy>()),
68 68 simpleColorHue(std::make_shared<SimpleColorHueStrategy>()),
69 69 extendedColorHue(std::make_shared<ExtendedColorHueStrategy>())
70   -{}
  70 +{ }
71 71  
72   -Light LightFactory::createLight(const nlohmann::json& lightState, int id)
  72 +Light LightFactory::createLight(const nlohmann::json& lightState, int id, const std::shared_ptr<APICache>& baseCache)
73 73 {
74 74 std::string type = lightState.value("type", "");
75 75 // Ignore case
76 76 std::transform(type.begin(), type.end(), type.begin(), [](char c) { return std::tolower(c); });
77 77  
  78 + Light light = baseCache ? Light(id, baseCache) : Light(id, commands, nullptr, nullptr, nullptr, refreshDuration);
  79 +
78 80 if (type == "on/off light" || type == "on/off plug-in unit")
79 81 {
80   - Light light(id, commands, nullptr, nullptr, nullptr, refreshDuration);
81 82 light.colorType = ColorType::NONE;
82 83 return light;
83 84 }
84   - else if (type == "dimmable light" || type =="dimmable plug-in unit")
  85 + else if (type == "dimmable light" || type == "dimmable plug-in unit")
85 86 {
86   - Light light(id, commands, simpleBrightness, nullptr, nullptr, refreshDuration);
  87 + light.setBrightnessStrategy(simpleBrightness);
87 88 light.colorType = ColorType::NONE;
88 89 return light;
89 90 }
90 91 else if (type == "color temperature light")
91 92 {
92   - Light light(id, commands, simpleBrightness, simpleColorTemperature, nullptr, refreshDuration);
  93 + light.setBrightnessStrategy(simpleBrightness);
  94 + light.setColorTemperatureStrategy(simpleColorTemperature);
93 95 light.colorType = ColorType::TEMPERATURE;
94 96 return light;
95 97 }
96 98 else if (type == "color light")
97 99 {
98   - Light light(id, commands, simpleBrightness, nullptr, simpleColorHue, refreshDuration);
  100 + light.setBrightnessStrategy(simpleBrightness);
  101 + light.setColorHueStrategy(simpleColorHue);
99 102 light.colorType = getColorType(lightState, false);
100 103 return light;
101 104 }
102 105 else if (type == "extended color light")
103 106 {
104   - Light light(id, commands, simpleBrightness, extendedColorTemperature, extendedColorHue, refreshDuration);
  107 + light.setBrightnessStrategy(simpleBrightness);
  108 + light.setColorTemperatureStrategy(extendedColorTemperature);
  109 + light.setColorHueStrategy(extendedColorHue);
105 110 light.colorType = getColorType(lightState, true);
106 111 return light;
107 112 }
... ...
src/Light.cpp
... ... @@ -114,6 +114,9 @@ StateTransaction Light::transaction()
114 114  
115 115 Light::Light(int id, const HueCommandAPI& commands) : Light(id, commands, nullptr, nullptr, nullptr) { }
116 116  
  117 +Light::Light(int id, const std::shared_ptr<APICache>& baseCache) : BaseDevice(id, baseCache), colorType(ColorType::NONE)
  118 +{ }
  119 +
117 120 Light::Light(int id, const HueCommandAPI& commands, std::shared_ptr<const BrightnessStrategy> brightnessStrategy,
118 121 std::shared_ptr<const ColorTemperatureStrategy> colorTempStrategy,
119 122 std::shared_ptr<const ColorHueStrategy> colorHueStrategy, std::chrono::steady_clock::duration refreshDuration)
... ... @@ -122,6 +125,5 @@ Light::Light(int id, const HueCommandAPI&amp; commands, std::shared_ptr&lt;const Bright
122 125 brightnessStrategy(std::move(brightnessStrategy)),
123 126 colorTemperatureStrategy(std::move(colorTempStrategy)),
124 127 colorHueStrategy(std::move(colorHueStrategy))
125   -{
126   -}
  128 +{ }
127 129 } // namespace hueplusplus
... ...
src/Sensor.cpp
... ... @@ -230,6 +230,11 @@ bool Sensor::isPrimary() const
230 230 return primary.is_boolean() && primary.get<bool>();
231 231 }
232 232  
  233 +Sensor::Sensor(int id, const std::shared_ptr<APICache>& baseCache)
  234 + : BaseDevice(id, baseCache)
  235 +{ }
  236 +
  237 +
233 238 Sensor::Sensor(int id, const HueCommandAPI& commands, std::chrono::steady_clock::duration refreshDuration)
234 239 : BaseDevice(id, commands, "/sensors/", refreshDuration)
235 240 { }
... ...
test/test_ResourceList.cpp
... ... @@ -32,6 +32,7 @@ using namespace testing;
32 32 class TestResource
33 33 {
34 34 public:
  35 + TestResource(int id, std::shared_ptr<APICache> baseCache) {}
35 36 TestResource(int id, HueCommandAPI api, std::chrono::steady_clock::duration refreshDuration) : id(id) { }
36 37  
37 38 void refresh(bool force = false) { }
... ... @@ -47,6 +48,7 @@ public:
47 48 class TestStringResource
48 49 {
49 50 public:
  51 + TestStringResource(const std::string& id, std::shared_ptr<APICache> baseCache) {}
50 52 TestStringResource(const std::string& id, HueCommandAPI api, std::chrono::steady_clock::duration refreshDuration)
51 53 : id(id)
52 54 { }
... ... @@ -122,8 +124,8 @@ TEST(ResourceList, get)
122 124 const nlohmann::json state = {{"resource", "state"}};
123 125 const nlohmann::json response = {{std::to_string(id), state}};
124 126  
125   - MockFunction<TestResource(int, const nlohmann::json&)> factory;
126   - EXPECT_CALL(factory, Call(id, state))
  127 + MockFunction<TestResource(int, const nlohmann::json&, const std::shared_ptr<APICache>&)> factory;
  128 + EXPECT_CALL(factory, Call(id, state, std::shared_ptr<APICache>()))
127 129 .WillOnce(Return(TestResource(id, commands, std::chrono::steady_clock::duration::max())));
128 130  
129 131 ResourceList<TestResource, int> list(
... ... @@ -162,7 +164,7 @@ TEST(ResourceList, get)
162 164 }
163 165 {
164 166 ResourceList<TestResourceFactory, int> list(commands, path, std::chrono::steady_clock::duration::max(),
165   - [](int, const nlohmann::json&) { return TestResourceFactory(); });
  167 + [](int, const nlohmann::json&, const std::shared_ptr<APICache>&) { return TestResourceFactory(); });
166 168  
167 169 const int id = 2;
168 170 const nlohmann::json response = {{std::to_string(id), {{"resource", "state"}}}};
... ...