Procházet zdrojové kódy

Merge pull request #374 from greboid/dev4

Some more work on the channel who plugin.
pull/378/head
Chris Smith před 9 roky
rodič
revize
08e47d359d

+ 12
- 0
channelwho/src/com/dmdirc/addons/channelwho/ChannelWhoModule.java Zobrazit soubor

@@ -23,7 +23,13 @@
23 23
 package com.dmdirc.addons.channelwho;
24 24
 
25 25
 import com.dmdirc.ClientModule;
26
+import com.dmdirc.DMDircMBassador;
26 27
 import com.dmdirc.plugins.PluginDomain;
28
+import com.dmdirc.util.LoggingScheduledExecutorService;
29
+
30
+import java.util.concurrent.ScheduledExecutorService;
31
+
32
+import javax.inject.Named;
27 33
 
28 34
 import dagger.Module;
29 35
 import dagger.Provides;
@@ -44,4 +50,10 @@ public class ChannelWhoModule {
44 50
     public String getSettingsDomain() {
45 51
         return domain;
46 52
     }
53
+
54
+    @Provides
55
+    @Named("channelwho")
56
+    public ScheduledExecutorService getExecutorService(final DMDircMBassador eventBus) {
57
+        return new LoggingScheduledExecutorService(1, eventBus, "channelwho");
58
+    }
47 59
 }

+ 86
- 1
channelwho/src/com/dmdirc/addons/channelwho/ConnectionHandler.java Zobrazit soubor

@@ -22,8 +22,27 @@
22 22
 
23 23
 package com.dmdirc.addons.channelwho;
24 24
 
25
+import com.dmdirc.config.ConfigBinder;
26
+import com.dmdirc.config.ConfigBinding;
27
+import com.dmdirc.events.ChannelUserAwayEvent;
28
+import com.dmdirc.events.DisplayProperty;
29
+import com.dmdirc.events.ServerNumericEvent;
25 30
 import com.dmdirc.interfaces.Connection;
31
+import com.dmdirc.interfaces.ConnectionManager;
26 32
 import com.dmdirc.interfaces.GroupChat;
33
+import com.dmdirc.interfaces.GroupChatUser;
34
+import com.dmdirc.interfaces.config.AggregateConfigProvider;
35
+
36
+import com.google.common.annotations.VisibleForTesting;
37
+
38
+import java.util.HashMap;
39
+import java.util.Map;
40
+import java.util.Optional;
41
+import java.util.concurrent.ScheduledExecutorService;
42
+import java.util.concurrent.ScheduledFuture;
43
+import java.util.concurrent.TimeUnit;
44
+
45
+import net.engio.mbassy.listener.Handler;
27 46
 
28 47
 /**
29 48
  * Responsible for managing timers and settings required to who any {@link GroupChat}s on a
@@ -31,19 +50,85 @@ import com.dmdirc.interfaces.GroupChat;
31 50
  */
32 51
 public class ConnectionHandler {
33 52
 
53
+    private final Map<String, GroupChatUser> users;
34 54
     private final Connection connection;
35 55
     private final String domain;
56
+    private final ScheduledExecutorService executorService;
57
+    private final ConnectionManager connectionManager;
58
+    private final ConfigBinder configBinder;
59
+    private int whoInterval;
60
+    private ScheduledFuture<?> future;
36 61
 
37
-    public ConnectionHandler(final Connection connection, final String domain) {
62
+    public ConnectionHandler(
63
+            final AggregateConfigProvider config,
64
+            final ScheduledExecutorService executorService,
65
+            final ConnectionManager connectionManager, final String domain,
66
+            final Connection connection) {
38 67
         this.connection = connection;
39 68
         this.domain = domain;
69
+        this.executorService = executorService;
70
+        this.connectionManager = connectionManager;
71
+        configBinder = config.getBinder().withDefaultDomain(domain);
72
+        users = new HashMap<>();
40 73
     }
41 74
 
42 75
     public void load() {
76
+        configBinder.bind(this, ConnectionHandler.class);
43 77
         connection.getWindowModel().getEventBus().subscribe(this);
44 78
     }
45 79
 
46 80
     public void unload() {
81
+        configBinder.unbind(this);
82
+        executorService.shutdown();
47 83
         connection.getWindowModel().getEventBus().unsubscribe(this);
84
+        if (future != null) {
85
+            future.cancel(true);
86
+        }
87
+    }
88
+
89
+    @VisibleForTesting
90
+    void checkWho() {
91
+        connectionManager.getConnections().forEach(connection ->
92
+                connection.getGroupChatManager().getChannels().forEach(channel -> {
93
+            if (channel.getWindowModel().getConfigManager().getOptionBool(domain, "sendWho")) {
94
+                channel.requestUsersInfo();
95
+            }
96
+        }));
97
+    }
98
+
99
+    @VisibleForTesting
100
+    @ConfigBinding(key="whoInterval")
101
+    void handleWhoInterval(final int value) {
102
+        whoInterval = value;
103
+        if (future != null) {
104
+            future.cancel(true);
105
+        }
106
+        future = executorService.schedule(this::checkWho, whoInterval, TimeUnit.MILLISECONDS);
107
+    }
108
+
109
+    @VisibleForTesting
110
+    @Handler
111
+    void handleAwayEvent(final ChannelUserAwayEvent event) {
112
+        if (!event.getReason().isPresent()) {
113
+            event.setDisplayProperty(DisplayProperty.DO_NOT_DISPLAY, true);
114
+            users.put(event.getUser().getNickname(), event.getUser());
115
+            event.getChannel().getConnection()
116
+                    .ifPresent(c -> c.requestUserInfo(event.getUser().getUser()));
117
+        }
118
+    }
119
+
120
+    @VisibleForTesting
121
+    @Handler
122
+    void handleServerNumericEvent(final ServerNumericEvent event) {
123
+        if (event.getNumeric() == 301) {
124
+            final String nickname = event.getArgs()[4];
125
+            final String reason = event.getArgs()[5];
126
+            final GroupChatUser user = users.remove(nickname);
127
+            if (user != null) {
128
+                connection.getWindowModel().getEventBus().publishAsync(
129
+                        new ChannelUserAwayEvent(user.getGroupChat(), user,
130
+                                Optional.ofNullable(reason)));
131
+            }
132
+        }
48 133
     }
49 134
 }

+ 18
- 2
channelwho/src/com/dmdirc/addons/channelwho/ConnectionHandlerFactory.java Zobrazit soubor

@@ -22,25 +22,41 @@
22 22
 
23 23
 package com.dmdirc.addons.channelwho;
24 24
 
25
+import com.dmdirc.ClientModule.GlobalConfig;
25 26
 import com.dmdirc.interfaces.Connection;
27
+import com.dmdirc.interfaces.ConnectionManager;
28
+import com.dmdirc.interfaces.config.AggregateConfigProvider;
26 29
 import com.dmdirc.plugins.PluginDomain;
27 30
 
31
+import java.util.concurrent.ScheduledExecutorService;
32
+
28 33
 import javax.inject.Inject;
34
+import javax.inject.Named;
29 35
 
30 36
 /**
31 37
  * Factory for creating {@link ConnectionHandler}s.
32 38
  */
33 39
 public class ConnectionHandlerFactory {
34 40
 
41
+    private final AggregateConfigProvider config;
42
+    private final ScheduledExecutorService executorService;
43
+    private final ConnectionManager connectionManager;
35 44
     private final String domain;
36 45
 
37 46
     @Inject
38
-    public ConnectionHandlerFactory(@PluginDomain(ChannelWhoPlugin.class) final String domain) {
47
+    public ConnectionHandlerFactory(@GlobalConfig final AggregateConfigProvider config,
48
+            @Named("channelwho") final ScheduledExecutorService executorService,
49
+            final ConnectionManager connectionManager,
50
+            @PluginDomain(ChannelWhoPlugin.class) final String domain) {
51
+        this.config = config;
52
+        this.executorService = executorService;
53
+        this.connectionManager = connectionManager;
39 54
         this.domain = domain;
40 55
     }
41 56
 
42 57
     public ConnectionHandler get(final Connection connection) {
43
-        final ConnectionHandler handler = new ConnectionHandler(connection, domain);
58
+        final ConnectionHandler handler = new ConnectionHandler(config, executorService,
59
+                connectionManager, domain, connection);
44 60
         handler.load();
45 61
         return handler;
46 62
     }

+ 192
- 0
channelwho/test/com/dmdirc/addons/channelwho/ConnectionHandlerTest.java Zobrazit soubor

@@ -0,0 +1,192 @@
1
+/*
2
+ * Copyright (c) 2006-2015 DMDirc Developers
3
+ *
4
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
5
+ * of this software and associated documentation files (the "Software"), to deal
6
+ * in the Software without restriction, including without limitation the rights
7
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ * copies of the Software, and to permit persons to whom the Software is
9
+ * furnished to do so, subject to the following conditions:
10
+ *
11
+ * The above copyright notice and this permission notice shall be included in
12
+ * all copies or substantial portions of the Software.
13
+ *
14
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20
+ * SOFTWARE.
21
+ */
22
+
23
+package com.dmdirc.addons.channelwho;
24
+
25
+import com.dmdirc.DMDircMBassador;
26
+import com.dmdirc.config.ConfigBinder;
27
+import com.dmdirc.events.ChannelUserAwayEvent;
28
+import com.dmdirc.events.DisplayProperty;
29
+import com.dmdirc.events.ServerNumericEvent;
30
+import com.dmdirc.interfaces.Connection;
31
+import com.dmdirc.interfaces.ConnectionManager;
32
+import com.dmdirc.interfaces.GroupChat;
33
+import com.dmdirc.interfaces.GroupChatManager;
34
+import com.dmdirc.interfaces.GroupChatUser;
35
+import com.dmdirc.interfaces.User;
36
+import com.dmdirc.interfaces.WindowModel;
37
+import com.dmdirc.interfaces.config.AggregateConfigProvider;
38
+
39
+import com.google.common.collect.Lists;
40
+
41
+import java.util.Optional;
42
+import java.util.concurrent.ScheduledExecutorService;
43
+import java.util.concurrent.ScheduledFuture;
44
+import java.util.concurrent.TimeUnit;
45
+
46
+import org.junit.Before;
47
+import org.junit.Test;
48
+import org.junit.runner.RunWith;
49
+import org.mockito.ArgumentCaptor;
50
+import org.mockito.Captor;
51
+import org.mockito.Mock;
52
+import org.mockito.runners.MockitoJUnitRunner;
53
+
54
+import static org.junit.Assert.assertEquals;
55
+import static org.mockito.Matchers.any;
56
+import static org.mockito.Matchers.anyLong;
57
+import static org.mockito.Matchers.eq;
58
+import static org.mockito.Mockito.never;
59
+import static org.mockito.Mockito.verify;
60
+import static org.mockito.Mockito.when;
61
+
62
+@RunWith(MockitoJUnitRunner.class)
63
+public class ConnectionHandlerTest {
64
+
65
+    @Mock private AggregateConfigProvider config;
66
+    @Mock private ConfigBinder configBinder;
67
+    @Mock private WindowModel windowModel;
68
+    @Mock private DMDircMBassador eventBus;
69
+    @Mock private ScheduledExecutorService scheduledExecutorService;
70
+    @Mock private ScheduledFuture scheduledFuture;
71
+    @Mock private ConnectionManager connectionManager;
72
+    @Mock private Connection connection;
73
+    @Mock private GroupChat groupChat;
74
+    @Mock private GroupChatUser groupChatUser;
75
+    @Mock private User user;
76
+    @Mock private GroupChatManager groupChatManager;
77
+    @Mock private ServerNumericEvent serverNumericEvent;
78
+    @Mock private ChannelUserAwayEvent channelUserAwayEvent;
79
+    @Captor private ArgumentCaptor<ChannelUserAwayEvent> eventArgumentCaptor;
80
+    private ConnectionHandler instance;
81
+
82
+    @Before
83
+    public void setUp() throws Exception {
84
+        when(scheduledExecutorService.schedule(any(Runnable.class), anyLong(), any()))
85
+                .thenReturn(scheduledFuture);
86
+        when(windowModel.getEventBus()).thenReturn(eventBus);
87
+        when(connection.getWindowModel()).thenReturn(windowModel);
88
+        when(config.getBinder()).thenReturn(configBinder);
89
+        when(connectionManager.getConnections()).thenReturn(Lists.newArrayList(connection));
90
+        when(connection.getGroupChatManager()).thenReturn(groupChatManager);
91
+        when(groupChatManager.getChannels()).thenReturn(Lists.newArrayList(groupChat));
92
+        when(groupChat.getWindowModel()).thenReturn(windowModel);
93
+        when(groupChat.getConnection()).thenReturn(Optional.of(connection));
94
+        when(configBinder.withDefaultDomain("domain")).thenReturn(configBinder);
95
+        when(windowModel.getConfigManager()).thenReturn(config);
96
+        when(groupChatUser.getNickname()).thenReturn("nickname");
97
+        when(channelUserAwayEvent.getUser()).thenReturn(groupChatUser);
98
+        when(channelUserAwayEvent.getChannel()).thenReturn(groupChat);
99
+        when(groupChatUser.getUser()).thenReturn(user);
100
+        instance = new ConnectionHandler(config, scheduledExecutorService, connectionManager,
101
+                "domain", connection);
102
+        instance.handleWhoInterval(5);
103
+    }
104
+
105
+    @Test
106
+    public void testLoad() throws Exception {
107
+        instance.load();
108
+        verify(configBinder).bind(instance, ConnectionHandler.class);
109
+        verify(eventBus).subscribe(instance);
110
+        verify(scheduledExecutorService).schedule(any(Runnable.class), eq(5l),
111
+                eq(TimeUnit.MILLISECONDS));
112
+    }
113
+
114
+    @Test
115
+    public void testUnload() throws Exception {
116
+        instance.unload();
117
+        verify(configBinder).unbind(instance);
118
+        verify(scheduledExecutorService).shutdown();
119
+        verify(eventBus).unsubscribe(instance);
120
+    }
121
+
122
+    @Test
123
+    public void testHandleWhoInterval() throws Exception {
124
+        instance.handleWhoInterval(10);
125
+        verify(scheduledFuture).cancel(true);
126
+        verify(scheduledExecutorService).schedule(any(Runnable.class), eq(5l),
127
+                eq(TimeUnit.MILLISECONDS));
128
+        verify(scheduledExecutorService).schedule(any(Runnable.class), eq(10l),
129
+                eq(TimeUnit.MILLISECONDS));
130
+    }
131
+
132
+    @Test
133
+    public void testCheckWho_True() throws Exception {
134
+        when(config.getOptionBool("domain", "sendWho")).thenReturn(true);
135
+        instance.checkWho();
136
+        verify(config).getOptionBool("domain", "sendWho");
137
+        verify(groupChat).requestUsersInfo();
138
+    }
139
+
140
+    @Test
141
+    public void testCheckWho_False() throws Exception {
142
+        when(config.getOptionBool("domain", "sendWho")).thenReturn(false);
143
+        instance.checkWho();
144
+        verify(config).getOptionBool("domain", "sendWho");
145
+        verify(groupChat, never()).requestUsersInfo();
146
+    }
147
+
148
+    @Test
149
+    public void testHandleAwayEvent_WithReason() throws Exception {
150
+        when(channelUserAwayEvent.getReason()).thenReturn(Optional.ofNullable("reason"));
151
+        instance.load();
152
+        instance.handleAwayEvent(channelUserAwayEvent);
153
+        verify(channelUserAwayEvent, never())
154
+                .setDisplayProperty(DisplayProperty.DO_NOT_DISPLAY, true);
155
+        verify(connection, never()).requestUserInfo(any());
156
+    }
157
+
158
+    @Test
159
+    public void testHandleAwayEvent_WithoutReason() throws Exception {
160
+        when(channelUserAwayEvent.getReason()).thenReturn(Optional.empty());
161
+        instance.load();
162
+        instance.handleAwayEvent(channelUserAwayEvent);
163
+        verify(channelUserAwayEvent).setDisplayProperty(DisplayProperty.DO_NOT_DISPLAY, true);
164
+        verify(connection).requestUserInfo(any());
165
+    }
166
+
167
+    @Test
168
+    public void testHandleServerNumericEvent_301() throws Exception {
169
+        when(serverNumericEvent.getNumeric()).thenReturn(301);
170
+        when(serverNumericEvent.getArgs()).thenReturn(
171
+                new String[]{"", "", "", "", "nickname", "reason"});
172
+        instance.load();
173
+        when(channelUserAwayEvent.getReason()).thenReturn(Optional.empty());
174
+        when(groupChatUser.getGroupChat()).thenReturn(groupChat);
175
+        instance.handleAwayEvent(channelUserAwayEvent);
176
+        instance.handleServerNumericEvent(serverNumericEvent);
177
+        verify(eventBus).publishAsync(eventArgumentCaptor.capture());
178
+        assertEquals("nickname", eventArgumentCaptor.getValue().getUser().getNickname());
179
+        assertEquals("reason", eventArgumentCaptor.getValue().getReason().get());
180
+    }
181
+
182
+    @Test
183
+    public void testHandleServerNumericEvent_101() throws Exception {
184
+        when(serverNumericEvent.getNumeric()).thenReturn(101);
185
+        when(channelUserAwayEvent.getReason()).thenReturn(Optional.empty());
186
+        instance.load();
187
+        instance.handleAwayEvent(channelUserAwayEvent);
188
+        instance.handleServerNumericEvent(serverNumericEvent);
189
+        verify(serverNumericEvent, never()).getArgs();
190
+        verify(eventBus, never()).publishAsync(any());
191
+    }
192
+}

Načítá se…
Zrušit
Uložit