~thomas-voss/location-service/fix-1347887

« back to all changes in this revision

Viewing changes to tests/provider_test.cpp

This MP consolidates multiple related changes together, with the goal of:

(1.) Make the service instance accessible via a cli. Useful for testing scenarios.
(2.) To cut down time-to-first-fix (ttff) by:
  (2.1) Leveraging SUPL and other supplementary data downloaded over ordinary data connections.
  (2.2) Enabling network-based positioning providers to acquire fast position estimates.

In more detail:

* Added tests for daemon and cli.
* Unified daemon and cli header and implementation files.
* Add a command-line interface to the service.
* Split up provider selection policy to rely on an interface ProviderEnumerator to ease in testing.
* Trimmed down on types.
* Removed connectivity API draft to prepare for simpler approach.
* Refactored includes.
* Added a configuration option to handle cell and wifi ID reporting.
* Add a mock for a connectivity API exposed to providers and reporters.
* Add units for connectivity api.
* Refactor cell class into namespace radio. Fixes: 1226204, 1248973, 1281817

Show diffs side-by-side

added added

removed removed

Lines of Context:
15
15
 *
16
16
 * Authored by: Thomas Voß <thomas.voss@canonical.com>
17
17
 */
18
 
#include "com/ubuntu/location/provider.h"
 
18
#include <com/ubuntu/location/provider.h>
19
19
 
20
20
#include <gmock/gmock.h>
21
21
#include <gtest/gtest.h>
24
24
 
25
25
namespace
26
26
{
 
27
template<typename T>
 
28
cul::Update<T> update_as_of_now(const T& value = T())
 
29
{
 
30
    return cul::Update<T>{value, cul::Clock::now()};
 
31
}
 
32
 
27
33
class DummyProvider : public com::ubuntu::location::Provider
28
34
{
29
35
public:
30
 
    DummyProvider(com::ubuntu::location::Provider::FeatureFlags feature_flags = com::ubuntu::location::Provider::FeatureFlags {},
31
 
                  com::ubuntu::location::Provider::RequirementFlags requirement_flags = com::ubuntu::location::Provider::RequirementFlags {})
32
 
        : com::ubuntu::location::Provider(feature_flags, requirement_flags)
 
36
    DummyProvider(cul::Provider::Features feats = cul::Provider::Features::none,
 
37
                  cul::Provider::Requirements requs= cul::Provider::Requirements::none)
 
38
        : com::ubuntu::location::Provider(feats, requs)
33
39
    {
34
40
    }
35
41
 
36
42
    void inject_update(const com::ubuntu::location::Update<com::ubuntu::location::Position>& update)
37
43
    {
38
 
        deliver_position_updates(update);
 
44
        mutable_updates().position(update);
39
45
    }
40
46
 
41
47
    void inject_update(const com::ubuntu::location::Update<com::ubuntu::location::Velocity>& update)
42
48
    {
43
 
        deliver_velocity_updates(update);
 
49
        mutable_updates().velocity(update);
44
50
    }
45
51
 
46
52
    void inject_update(const com::ubuntu::location::Update<com::ubuntu::location::Heading>& update)
47
53
    {
48
 
        deliver_heading_updates(update);
 
54
        mutable_updates().heading(update);
49
55
    }
50
56
};
51
57
}
52
58
 
53
59
TEST(Provider, requirement_flags_passed_at_construction_are_correctly_stored)
54
60
{
55
 
    com::ubuntu::location::Provider::FeatureFlags feature_flags;
56
 
    com::ubuntu::location::Provider::RequirementFlags requirement_flags;
57
 
    requirement_flags.set();
58
 
    DummyProvider provider(feature_flags, requirement_flags);
59
 
 
60
 
    EXPECT_TRUE(provider.requires(com::ubuntu::location::Provider::Requirement::satellites));
61
 
    EXPECT_TRUE(provider.requires(com::ubuntu::location::Provider::Requirement::cell_network));
62
 
    EXPECT_TRUE(provider.requires(com::ubuntu::location::Provider::Requirement::data_network));
63
 
    EXPECT_TRUE(provider.requires(com::ubuntu::location::Provider::Requirement::monetary_spending));
 
61
    cul::Provider::Features features = cul::Provider::Features::none;
 
62
    cul::Provider::Requirements requirements =
 
63
            cul::Provider::Requirements::cell_network |
 
64
            cul::Provider::Requirements::data_network |
 
65
            cul::Provider::Requirements::monetary_spending |
 
66
            cul::Provider::Requirements::satellites;
 
67
 
 
68
    DummyProvider provider(features, requirements);
 
69
 
 
70
    EXPECT_TRUE(provider.requires(com::ubuntu::location::Provider::Requirements::satellites));
 
71
    EXPECT_TRUE(provider.requires(com::ubuntu::location::Provider::Requirements::cell_network));
 
72
    EXPECT_TRUE(provider.requires(com::ubuntu::location::Provider::Requirements::data_network));
 
73
    EXPECT_TRUE(provider.requires(com::ubuntu::location::Provider::Requirements::monetary_spending));
64
74
}
65
75
 
66
76
TEST(Provider, feature_flags_passed_at_construction_are_correctly_stored)
67
77
{
68
 
    com::ubuntu::location::Provider::FeatureFlags flags;
69
 
    flags.set();
70
 
    DummyProvider provider(flags);
 
78
    cul::Provider::Features all_features
 
79
        = cul::Provider::Features::heading |
 
80
          cul::Provider::Features::position |
 
81
          cul::Provider::Features::velocity;
 
82
    DummyProvider provider(all_features);
71
83
 
72
 
    EXPECT_TRUE(provider.supports(com::ubuntu::location::Provider::Feature::position));
73
 
    EXPECT_TRUE(provider.supports(com::ubuntu::location::Provider::Feature::velocity));
74
 
    EXPECT_TRUE(provider.supports(com::ubuntu::location::Provider::Feature::heading));
 
84
    EXPECT_TRUE(provider.supports(com::ubuntu::location::Provider::Features::position));
 
85
    EXPECT_TRUE(provider.supports(com::ubuntu::location::Provider::Features::velocity));
 
86
    EXPECT_TRUE(provider.supports(com::ubuntu::location::Provider::Features::heading));
75
87
}
76
88
 
77
89
TEST(Provider, delivering_a_message_invokes_subscribers)
81
93
    bool heading_update_triggered {false};
82
94
    bool velocity_update_triggered {false};
83
95
 
84
 
    dp.subscribe_to_position_updates([&](const com::ubuntu::location::Update<com::ubuntu::location::Position>&)
85
 
    {
86
 
        position_update_triggered = true;
87
 
    });
88
 
 
89
 
    dp.subscribe_to_heading_updates([&](const com::ubuntu::location::Update<com::ubuntu::location::Heading>&)
90
 
    {
91
 
        heading_update_triggered = true;
92
 
    });
93
 
 
94
 
    dp.subscribe_to_velocity_updates([&](const com::ubuntu::location::Update<com::ubuntu::location::Velocity>&)
95
 
    {
96
 
        velocity_update_triggered = true;
97
 
    });
98
 
 
99
 
    dp.inject_update(com::ubuntu::location::Update<com::ubuntu::location::Position>());
100
 
    dp.inject_update(com::ubuntu::location::Update<com::ubuntu::location::Heading>());
101
 
    dp.inject_update(com::ubuntu::location::Update<com::ubuntu::location::Velocity>());
 
96
    auto c1 = dp.updates().position.connect(
 
97
        [&](const com::ubuntu::location::Update<com::ubuntu::location::Position>&)
 
98
        {
 
99
            position_update_triggered = true;
 
100
        });
 
101
 
 
102
    auto c2 = dp.updates().heading.connect(
 
103
        [&](const com::ubuntu::location::Update<com::ubuntu::location::Heading>&)
 
104
        {
 
105
            heading_update_triggered = true;
 
106
        });
 
107
 
 
108
    auto c3 = dp.updates().velocity.connect(
 
109
        [&](const com::ubuntu::location::Update<com::ubuntu::location::Velocity>&)
 
110
        {
 
111
            velocity_update_triggered = true;
 
112
        });
 
113
 
 
114
    dp.inject_update(update_as_of_now<cul::Position>());
 
115
    dp.inject_update(update_as_of_now<cul::Heading>());
 
116
    dp.inject_update(update_as_of_now<cul::Velocity>());
102
117
 
103
118
    EXPECT_TRUE(position_update_triggered);
104
119
    EXPECT_TRUE(heading_update_triggered);
109
124
{
110
125
struct MockProvider : public com::ubuntu::location::Provider
111
126
{
112
 
    MockProvider()
113
 
    {
114
 
    }
115
 
 
116
 
    MOCK_METHOD1(subscribe_to_position_updates, cul::ChannelConnection (std::function<void(const cul::Update<cul::Position>&)>));
117
 
    MOCK_METHOD1(subscribe_to_heading_updates, cul::ChannelConnection (std::function<void(const cul::Update<cul::Heading>&)>));
118
 
    MOCK_METHOD1(subscribe_to_velocity_updates, cul::ChannelConnection (std::function<void(const cul::Update<cul::Velocity>&)> f));
 
127
    MockProvider() : cul::Provider()
 
128
    {
 
129
    }
 
130
 
 
131
    void inject_update(const cul::Update<cul::Position>& update)
 
132
    {
 
133
        mutable_updates().position(update);
 
134
    }
 
135
 
 
136
    void inject_update(const cul::Update<cul::Velocity>& update)
 
137
    {
 
138
        mutable_updates().velocity(update);
 
139
    }
 
140
 
 
141
    void inject_update(const cul::Update<cul::Heading>& update)
 
142
    {
 
143
        mutable_updates().heading(update);
 
144
    }
119
145
 
120
146
    MOCK_METHOD0(start_position_updates, void());
121
147
    MOCK_METHOD0(stop_position_updates, void());
160
186
    EXPECT_FALSE(provider.state_controller()->are_velocity_updates_running());
161
187
}
162
188
 
163
 
#include "com/ubuntu/location/proxy_provider.h"
164
 
 
165
 
TEST(ProxyProvider, start_and_stop_does_not_throw_for_null_providers)
166
 
{
167
 
    cul::ProviderSelection selection;
168
 
    cul::ProxyProvider pp{selection};
169
 
 
170
 
    EXPECT_NO_THROW(pp.start_position_updates());
171
 
    EXPECT_NO_THROW(pp.stop_position_updates());
172
 
 
173
 
    EXPECT_NO_THROW(pp.start_heading_updates());
174
 
    EXPECT_NO_THROW(pp.stop_heading_updates());
175
 
 
176
 
    EXPECT_NO_THROW(pp.start_velocity_updates());
177
 
    EXPECT_NO_THROW(pp.stop_velocity_updates());
178
 
}
179
 
 
180
 
TEST(ProxyProvider, setting_up_signal_connections_does_not_throw_for_null_providers)
181
 
{
182
 
    cul::ProviderSelection selection;
183
 
    cul::ProxyProvider pp{selection};
184
 
 
185
 
    EXPECT_NO_THROW(pp.subscribe_to_position_updates([](const cul::Update<cul::Position>&){}));
186
 
    EXPECT_NO_THROW(pp.subscribe_to_heading_updates([](const cul::Update<cul::Heading>&){}));
187
 
    EXPECT_NO_THROW(pp.subscribe_to_velocity_updates([](const cul::Update<cul::Velocity>&){}));
188
 
}
 
189
#include <com/ubuntu/location/proxy_provider.h>
189
190
 
190
191
TEST(ProxyProvider, start_and_stop_of_updates_propagates_to_correct_providers)
191
192
{
217
218
    pp.stop_velocity_updates();
218
219
}
219
220
 
 
221
struct MockEventConsumer
 
222
{
 
223
    MOCK_METHOD1(on_new_position, void(const cul::Update<cul::Position>&));
 
224
    MOCK_METHOD1(on_new_velocity, void(const cul::Update<cul::Velocity>&));
 
225
    MOCK_METHOD1(on_new_heading, void(const cul::Update<cul::Heading>&));
 
226
};
 
227
 
220
228
TEST(ProxyProvider, update_signals_are_routed_from_correct_providers)
221
229
{
222
230
    using namespace ::testing;
223
231
    
224
232
    NiceMock<MockProvider> mp1, mp2, mp3;
225
 
    EXPECT_CALL(mp1, subscribe_to_position_updates(_)).Times(Exactly(1)).WillRepeatedly(Return(cul::ChannelConnection{}));
226
 
    EXPECT_CALL(mp2, subscribe_to_heading_updates(_)).Times(Exactly(1)).WillRepeatedly(Return(cul::ChannelConnection{}));
227
 
    EXPECT_CALL(mp3, subscribe_to_velocity_updates(_)).Times(Exactly(1)).WillRepeatedly(Return(cul::ChannelConnection{}));
228
233
 
229
234
    cul::Provider::Ptr p1{std::addressof(mp1), [](cul::Provider*){}};
230
235
    cul::Provider::Ptr p2{std::addressof(mp2), [](cul::Provider*){}};
234
239
 
235
240
    cul::ProxyProvider pp{selection};
236
241
 
237
 
    mp1.subscribe_to_position_updates([](const cul::Update<cul::Position>&){});
238
 
    mp2.subscribe_to_heading_updates([](const cul::Update<cul::Heading>&){});
239
 
    mp3.subscribe_to_velocity_updates([](const cul::Update<cul::Velocity>&){});
 
242
    NiceMock<MockEventConsumer> mec;
 
243
    EXPECT_CALL(mec, on_new_position(_)).Times(1);
 
244
    EXPECT_CALL(mec, on_new_velocity(_)).Times(1);
 
245
    EXPECT_CALL(mec, on_new_heading(_)).Times(1);
 
246
 
 
247
    pp.updates().position.connect([&mec](const cul::Update<cul::Position>& p){mec.on_new_position(p);});
 
248
    pp.updates().heading.connect([&mec](const cul::Update<cul::Heading>& h){mec.on_new_heading(h);});
 
249
    pp.updates().velocity.connect([&mec](const cul::Update<cul::Velocity>& v){mec.on_new_velocity(v);});
 
250
 
 
251
    mp1.inject_update(cul::Update<cul::Position>());
 
252
    mp2.inject_update(cul::Update<cul::Heading>());
 
253
    mp3.inject_update(cul::Update<cul::Velocity>());
240
254
}