~ps-jenkins/indicator-transfer/ubuntu-vivid-proposed

« back to all changes in this revision

Viewing changes to tests/test-view-gmenu.cpp

  • Committer: Ted Gould
  • Author(s): Charles Kerr
  • Date: 2014-06-18 19:26:56 UTC
  • mfrom: (1.2.20 indicator-transfer)
  • Revision ID: ted@gould.cx-20140618192656-ufycr3k7g5w0en4u
This sets up the code layout, menu, indicator, unit tests, code coverage rules, etc... what you'd expect from an indicator.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright 2014 Canonical Ltd.
 
3
 *
 
4
 * This program is free software: you can redistribute it and/or modify it
 
5
 * under the terms of the GNU General Public License version 3, as published
 
6
 * by the Free Software Foundation.
 
7
 *
 
8
 * This program is distributed in the hope that it will be useful, but
 
9
 * WITHOUT ANY WARRANTY; without even the implied warranties of
 
10
 * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
 
11
 * PURPOSE.  See the GNU General Public License for more details.
 
12
 *
 
13
 * You should have received a copy of the GNU General Public License along
 
14
 * with this program.  If not, see <http://www.gnu.org/licenses/>.
 
15
 *
 
16
 * Authors:
 
17
 *   Charles Kerr <charles.kerr@canonical.com>
 
18
 */
 
19
 
 
20
#include "glib-fixture.h"
 
21
#include "controller-mock.h"
 
22
#include "world-mock.h"
 
23
 
 
24
#include <transfer/dbus-shared.h>
 
25
#include <transfer/view-gmenu.h>
 
26
 
 
27
 
 
28
using namespace unity::indicator::transfer;
 
29
 
 
30
class GMenuViewFixture: public GlibFixture
 
31
{
 
32
private:
 
33
  typedef GlibFixture super;
 
34
 
 
35
protected:
 
36
 
 
37
  GTestDBus* bus = nullptr;
 
38
  std::shared_ptr<MockWorld> m_world;
 
39
  std::shared_ptr<MutableModel> m_model;
 
40
  std::shared_ptr<MockController> m_controller;
 
41
  std::shared_ptr<GMenuView> m_view;
 
42
 
 
43
  void SetUp()
 
44
  {
 
45
    super::SetUp();
 
46
 
 
47
    // bring up the test bus
 
48
    bus = g_test_dbus_new(G_TEST_DBUS_NONE);
 
49
    g_test_dbus_up(bus);
 
50
    const auto address = g_test_dbus_get_bus_address(bus);
 
51
    g_setenv("DBUS_SYSTEM_BUS_ADDRESS", address, true);
 
52
    g_setenv("DBUS_SESSION_BUS_ADDRESS", address, true);
 
53
 
 
54
    // bring up the world
 
55
    m_world.reset(new MockWorld);
 
56
    m_model.reset(new MutableModel);
 
57
    std::shared_ptr<Transfer> t;
 
58
    t.reset(new Transfer);
 
59
    t->id = "a";
 
60
    t->state = Transfer::RUNNING;
 
61
    m_model->add(t);
 
62
    t.reset(new Transfer);
 
63
    t->id = "b";
 
64
    t->state = Transfer::PAUSED;
 
65
    m_model->add(t);
 
66
    t.reset(new Transfer);
 
67
    t->id = "c";
 
68
    t->state = Transfer::FINISHED;
 
69
    m_model->add(t);
 
70
    m_controller.reset(new MockController(m_model, m_world));
 
71
    m_view.reset(new GMenuView(m_model, m_controller));
 
72
  }
 
73
 
 
74
  void TearDown()
 
75
  {
 
76
    // empty the world
 
77
    m_view.reset();
 
78
    m_controller.reset();
 
79
    m_model.reset();
 
80
    m_world.reset();
 
81
 
 
82
    // bring down the bus
 
83
    GError * error = nullptr;
 
84
    GDBusConnection* connection = g_bus_get_sync(G_BUS_TYPE_SESSION, nullptr, &error);
 
85
    if(!g_dbus_connection_is_closed(connection))
 
86
      g_dbus_connection_close_sync(connection, nullptr, &error);
 
87
    g_assert_no_error(error);
 
88
    g_clear_object(&connection);
 
89
    g_test_dbus_down(bus);
 
90
    g_clear_object(&bus);
 
91
 
 
92
    super::TearDown();
 
93
  }
 
94
};
 
95
 
 
96
/***
 
97
****
 
98
***/
 
99
 
 
100
/**
 
101
 * These two are more about testing the scaffolding.
 
102
 * If the objects listening to the bus don't all get
 
103
 * torn down correctly, the second time we setup the
 
104
 * fixture we'll see glib errors
 
105
 */
 
106
 
 
107
TEST_F(GMenuViewFixture, CanFixtureSetupOnce)
 
108
{
 
109
  g_timeout_add_seconds(1, [](gpointer g){
 
110
    g_main_loop_quit(static_cast<GMainLoop*>(g));
 
111
    return G_SOURCE_REMOVE;
 
112
  }, loop);
 
113
  g_main_loop_run(loop);
 
114
}
 
115
 
 
116
TEST_F(GMenuViewFixture, CanFixtureSetupTwice)
 
117
{
 
118
  g_timeout_add_seconds(1, [](gpointer g){
 
119
    g_main_loop_quit(static_cast<GMainLoop*>(g));
 
120
    return G_SOURCE_REMOVE;
 
121
  }, loop);
 
122
  g_main_loop_run(loop);
 
123
}
 
124
 
 
125
/***
 
126
****
 
127
****  GActions
 
128
****
 
129
***/
 
130
 
 
131
/* Make sure all the actions we expect are there */
 
132
TEST_F(GMenuViewFixture, ExportedActions)
 
133
{
 
134
  wait_msec();
 
135
 
 
136
  // these are the actions we expect to find
 
137
  const std::set<std::string> expected_actions {
 
138
    "activate-transfer",
 
139
    "cancel-transfer",
 
140
    "clear-all",
 
141
    "open-app-transfer",
 
142
    "open-transfer",
 
143
    "pause-transfer",
 
144
    "pause-all",
 
145
    "phone-header",
 
146
    "resume-all",
 
147
    "resume-transfer",
 
148
    "transfer-states"
 
149
  };
 
150
 
 
151
  auto connection = g_bus_get_sync(G_BUS_TYPE_SESSION, nullptr, nullptr);
 
152
  auto exported = g_dbus_action_group_get(connection, BUS_NAME, BUS_PATH);
 
153
  auto names_strv = g_action_group_list_actions(G_ACTION_GROUP(exported));
 
154
 
 
155
  // wait for the exported ActionGroup to be populated
 
156
  if (g_strv_length(names_strv) == 0)
 
157
    {
 
158
      g_strfreev(names_strv);
 
159
      wait_for_signal(exported, "action-added");
 
160
      names_strv = g_action_group_list_actions(G_ACTION_GROUP(exported));
 
161
    }
 
162
 
 
163
  // convert it to a std::set for easy prodding
 
164
  std::set<std::string> actions;
 
165
  for(int i=0; names_strv && names_strv[i]; i++)
 
166
    actions.insert(names_strv[i]);
 
167
 
 
168
  EXPECT_EQ(expected_actions, actions);
 
169
 
 
170
  // try closing the connection prematurely
 
171
  // to test Exporter's name-lost signal
 
172
  bool name_lost = false;
 
173
  m_view->name_lost().connect([this,&name_lost](){
 
174
    name_lost = true;
 
175
    g_main_loop_quit(loop);
 
176
  });
 
177
  g_dbus_connection_close_sync(connection, nullptr, nullptr);
 
178
  g_main_loop_run(loop);
 
179
  EXPECT_TRUE(name_lost);
 
180
 
 
181
  // cleanup
 
182
  g_strfreev(names_strv);
 
183
  g_clear_object(&exported);
 
184
  g_clear_object(&connection);
 
185
}
 
186
 
 
187
TEST_F(GMenuViewFixture, InvokedGActionsCallTheController)
 
188
{
 
189
  wait_msec();
 
190
  auto connection = g_bus_get_sync(G_BUS_TYPE_SESSION, nullptr, nullptr);
 
191
  auto dbus_action_group = g_dbus_action_group_get(connection, BUS_NAME, BUS_PATH);
 
192
  auto action_group = G_ACTION_GROUP(dbus_action_group);
 
193
 
 
194
  // wait for the exported ActionGroup to be populated
 
195
  auto names_strv = g_action_group_list_actions(action_group);
 
196
  if (g_strv_length(names_strv) == 0)
 
197
    {
 
198
      g_strfreev(names_strv);
 
199
      wait_for_signal(dbus_action_group, "action-added");
 
200
      names_strv = g_action_group_list_actions(action_group);
 
201
    }
 
202
  g_strfreev(names_strv);
 
203
 
 
204
  // try tapping a transfer that can be resumed
 
205
  const char* id = "b";
 
206
  EXPECT_TRUE(m_model->get(id)->can_resume());
 
207
  EXPECT_CALL(*m_controller, tap(id)).Times(1);
 
208
  g_action_group_activate_action(action_group, "activate-transfer", g_variant_new_string(id));
 
209
  wait_msec();
 
210
 
 
211
  // try tapping a transfer that CAN'T be resumed
 
212
  id = "c";
 
213
  EXPECT_TRUE(!m_model->get(id)->can_resume());
 
214
  EXPECT_CALL(*m_controller, tap(id)).Times(1);
 
215
  g_action_group_activate_action(action_group, "activate-transfer", g_variant_new_string(id));
 
216
  wait_msec();
 
217
 
 
218
  // try cancelling a transfer
 
219
  id = "a";
 
220
  EXPECT_CALL(*m_controller, cancel(id)).Times(1);
 
221
  g_action_group_activate_action(action_group, "cancel-transfer", g_variant_new_string(id));
 
222
  wait_msec();
 
223
 
 
224
  // try opening a transfer
 
225
  id = "b";
 
226
  EXPECT_CALL(*m_controller, open(id)).Times(1);
 
227
  g_action_group_activate_action(action_group, "open-transfer", g_variant_new_string(id));
 
228
  wait_msec();
 
229
 
 
230
  // try opening a transfer's recipient's app
 
231
  id = "c";
 
232
  EXPECT_CALL(*m_controller, open_app(id)).Times(1);
 
233
  g_action_group_activate_action(action_group, "open-app-transfer", g_variant_new_string(id));
 
234
  wait_msec();
 
235
 
 
236
  // try calling clear-all
 
237
  EXPECT_CALL(*m_controller, clear_all()).Times(1);
 
238
  g_action_group_activate_action(action_group, "clear-all", nullptr);
 
239
  wait_msec();
 
240
 
 
241
  // try pausing a transfer
 
242
  id = "a";
 
243
  EXPECT_CALL(*m_controller, pause(id)).Times(1);
 
244
  g_action_group_activate_action(action_group, "pause-transfer", g_variant_new_string(id));
 
245
  wait_msec();
 
246
 
 
247
  // try calling pause-all
 
248
  EXPECT_CALL(*m_controller, pause_all()).Times(1);
 
249
  g_action_group_activate_action(action_group, "pause-all", nullptr);
 
250
  wait_msec();
 
251
 
 
252
  // try calling resume-all
 
253
  EXPECT_CALL(*m_controller, resume_all()).Times(1);
 
254
  g_action_group_activate_action(action_group, "resume-all", nullptr);
 
255
  wait_msec();
 
256
 
 
257
  // try resuming a transfer
 
258
  id = "a";
 
259
  EXPECT_CALL(*m_controller, resume(id)).Times(1);
 
260
  g_action_group_activate_action(action_group, "resume-transfer", g_variant_new_string(id));
 
261
  wait_msec();
 
262
 
 
263
  // cleanup
 
264
  g_clear_object(&dbus_action_group);
 
265
  g_clear_object(&connection);
 
266
}
 
267
 
 
268
/***
 
269
****
 
270
****  GMenu
 
271
****
 
272
***/
 
273
 
 
274
TEST_F(GMenuViewFixture, DoesExportMenu)
 
275
{
 
276
  wait_msec();
 
277
 
 
278
  auto connection = g_bus_get_sync(G_BUS_TYPE_SESSION, nullptr, nullptr);
 
279
  auto dbus_menu_model = g_dbus_menu_model_get(connection, BUS_NAME, BUS_PATH"/phone");
 
280
  auto menu_model = G_MENU_MODEL(dbus_menu_model);
 
281
 
 
282
  // query the GDBusMenuModel for information to activate it
 
283
  int n = g_menu_model_get_n_items(menu_model);
 
284
  if (!n)
 
285
    {
 
286
      // give the model a moment to populate its info
 
287
      wait_msec(100);
 
288
      n = g_menu_model_get_n_items(menu_model);
 
289
    }
 
290
 
 
291
  EXPECT_TRUE(menu_model != nullptr);
 
292
  EXPECT_NE(0, n);
 
293
 
 
294
  // cleanup
 
295
  g_clear_object(&dbus_menu_model);
 
296
  g_clear_object(&connection);
 
297
}
 
298