1   /*****************************************************************
2    * Licensed to the Apache Software Foundation (ASF) under one   *
3    * or more contributor license agreements.  See the NOTICE file *
4    * distributed with this work for additional information        *
5    * regarding copyright ownership.  The ASF licenses this file   *
6    * to you under the Apache License, Version 2.0 (the            *
7    * "License"); you may not use this file except in compliance   *
8    * with the License.  You may obtain a copy of the License at   *
9    *                                                              *
10   *   http://www.apache.org/licenses/LICENSE-2.0                 *
11   *                                                              *
12   * Unless required by applicable law or agreed to in writing,   *
13   * software distributed under the License is distributed on an  *
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
15   * KIND, either express or implied.  See the License for the    *
16   * specific language governing permissions and limitations      *
17   * under the License.                                           *
18   ****************************************************************/
19  
20  
21  
22  package org.apache.james.remotemanager;
23  
24  import org.apache.avalon.cornerstone.services.sockets.SocketManager;
25  import org.apache.avalon.cornerstone.services.threads.ThreadManager;
26  import org.apache.avalon.framework.container.ContainerUtil;
27  import org.apache.avalon.framework.service.ServiceException;
28  import org.apache.commons.net.telnet.TelnetClient;
29  import org.apache.james.services.JamesConnectionManager;
30  import org.apache.james.services.MailServer;
31  import org.apache.james.services.UsersRepository;
32  import org.apache.james.services.UsersStore;
33  import org.apache.james.test.mock.avalon.MockLogger;
34  import org.apache.james.test.mock.avalon.MockServiceManager;
35  import org.apache.james.test.mock.avalon.MockSocketManager;
36  import org.apache.james.test.mock.avalon.MockThreadManager;
37  import org.apache.james.test.mock.james.MockMailServer;
38  import org.apache.james.test.mock.james.MockUsersStore;
39  import org.apache.james.test.util.Util;
40  import org.apache.james.userrepository.MockUsersRepository;
41  import org.apache.james.util.InternetPrintWriter;
42  import org.apache.james.util.connection.SimpleConnectionManager;
43  
44  import java.io.BufferedInputStream;
45  import java.io.BufferedOutputStream;
46  import java.io.BufferedReader;
47  import java.io.IOException;
48  import java.io.InputStreamReader;
49  import java.util.ArrayList;
50  import java.util.Iterator;
51  import java.util.List;
52  
53  import junit.framework.TestCase;
54  
55  /***
56   * Tests the org.apache.james.remotemanager.RemoteManager
57   * TODO: impl missing command tests for: 
58   *       USER 
59   *       SHUTDOWN (hard to test, because it does shutdown the whole (testing) JVM 
60   */
61  
62  public class RemoteManagerTest extends TestCase {
63      
64      protected int m_remoteManagerListenerPort = Util.getNonPrivilegedPort();
65      protected RemoteManager m_remoteManager;
66      protected RemoteManagerTestConfiguration m_testConfiguration;
67      protected String m_host = "127.0.0.1";
68      protected BufferedReader m_reader;
69      protected InternetPrintWriter m_writer;
70      protected TelnetClient m_telnetClient;
71      private MockUsersRepository m_mockUsersRepository;
72      private MockMailServer mailServer;
73  
74      protected void setUp() throws Exception {
75          m_remoteManager = new RemoteManager();
76          ContainerUtil.enableLogging(m_remoteManager, new MockLogger());
77          ContainerUtil.service(m_remoteManager, setUpServiceManager());
78          m_testConfiguration = new RemoteManagerTestConfiguration(m_remoteManagerListenerPort);
79      }
80  
81      protected void tearDown() throws Exception {
82          ContainerUtil.dispose(mailServer);
83          super.tearDown();
84      }
85  
86      protected void finishSetUp(RemoteManagerTestConfiguration testConfiguration) {
87          testConfiguration.init();
88          try {
89              ContainerUtil.configure(m_remoteManager, testConfiguration);
90              ContainerUtil.initialize(m_remoteManager);
91          } catch (Exception e) {
92              throw new RuntimeException(e);
93          }
94      }
95  
96      protected void login() throws IOException {
97          login(m_testConfiguration.getLoginName(), m_testConfiguration.getLoginPassword());
98      }
99  
100     protected void login(String name, String password) throws IOException {
101         sendCommand(name);
102         List answers = readAnswer();
103         String last = getLastLine(answers);
104         assertTrue("Last line does not start with Password: "+last,last.startsWith("Password:"));
105         sendCommand(password);
106         answers = readAnswer();
107         last = getLastLine(answers);
108         assertTrue("Last line does not start with Welcome: "+last,last.startsWith("Welcome"));
109     }
110 
111     protected String getLastLine(List list) {
112         if (list == null || list.isEmpty()) return null;
113         return (String)list.get(list.size()-1);
114     }
115 
116     protected List readAnswer() {
117         return readAnswer(1);
118     }
119     
120     protected List readAnswer(int numLines) {
121         List allAnswerLines = new ArrayList();
122         try {
123             if (numLines > 0) {
124                 for (int i = 0; i < numLines; i++) {
125                     allAnswerLines.add(m_reader.readLine());
126                 }
127             } else {
128                 String line = m_reader.readLine();
129                 allAnswerLines.add(line);
130                 
131                 while (m_reader.ready()) {
132                     allAnswerLines.add(m_reader.readLine());
133                 }
134             }
135             return allAnswerLines;
136         } catch (IOException e) {
137             return null;
138         }
139     }
140 
141     protected void sendCommand(String command) throws IOException {
142         m_writer.println(command);
143         m_writer.flush();
144     }
145 
146     protected void connect() throws IOException {
147         m_telnetClient = new TelnetClient();
148         m_telnetClient.connect(m_host, m_remoteManagerListenerPort);
149 
150         m_reader = new BufferedReader(new InputStreamReader(new BufferedInputStream(m_telnetClient.getInputStream(), 1024), "ASCII"));
151         m_writer = new InternetPrintWriter(new BufferedOutputStream(m_telnetClient.getOutputStream(), 1024), true);
152         
153         readAnswer(3);
154     }
155 
156     private MockServiceManager setUpServiceManager() throws ServiceException {
157         MockServiceManager serviceManager = new MockServiceManager();
158         SimpleConnectionManager connectionManager = new SimpleConnectionManager();
159         ContainerUtil.enableLogging(connectionManager, new MockLogger());
160         serviceManager.put(JamesConnectionManager.ROLE, connectionManager);
161         mailServer = new MockMailServer();
162         serviceManager.put(MailServer.ROLE, mailServer);
163         m_mockUsersRepository = mailServer.getUsersRepository();
164         serviceManager.put(UsersRepository.ROLE, m_mockUsersRepository);
165         serviceManager.put(UsersStore.ROLE, new MockUsersStore(m_mockUsersRepository));
166         serviceManager.put(SocketManager.ROLE, new MockSocketManager(m_remoteManagerListenerPort));
167         serviceManager.put(ThreadManager.ROLE, new MockThreadManager());
168         return serviceManager;
169     }
170 
171     public void testLogin() throws IOException {
172         finishSetUp(m_testConfiguration);
173         connect();
174 
175         login();
176     }
177 
178     public void testWrongLoginUser() throws IOException {
179         finishSetUp(m_testConfiguration);
180         connect();
181 
182         sendCommand("sindbad");
183         List answers = readAnswer();
184         sendCommand(m_testConfiguration.getLoginPassword());
185 
186         
187         answers = readAnswer(2);
188         String last = getLastLine(answers);
189         assertTrue("Last line does not start with 'Login id:' but with '"+last+"'",last.startsWith("Login id:")); 
190     }
191 
192     public void testWrongLoginPassword() throws IOException {
193         finishSetUp(m_testConfiguration);
194         connect();
195 
196         sendCommand(m_testConfiguration.getLoginName());
197         List answers = readAnswer();
198         sendCommand("getmethru");
199 
200         answers = readAnswer(2);
201         String last = getLastLine(answers);
202         assertTrue("Line does not start with 'Login id:' but with '"+last+"'", last.startsWith("Login id:")); 
203     }
204 
205     public void testUserCount() throws IOException {
206         finishSetUp(m_testConfiguration);
207         connect();
208         login();
209 
210         sendCommand("countusers");
211         assertTrue(getLastLine(readAnswer()).endsWith(" 0")); 
212 
213         sendCommand("adduser testCount1 testCount");
214         assertTrue(getLastLine(readAnswer()).endsWith(" added")); 
215 
216         sendCommand("countusers");
217         assertTrue(getLastLine(readAnswer()).endsWith(" 1")); 
218 
219         sendCommand("adduser testCount2 testCount");
220         assertTrue(getLastLine(readAnswer()).endsWith(" added")); 
221 
222         sendCommand("countusers");
223         assertTrue(getLastLine(readAnswer()).endsWith(" 2")); 
224 
225         m_mockUsersRepository.removeUser("testCount1");
226 
227         sendCommand("countusers");
228         assertTrue(getLastLine(readAnswer()).endsWith(" 1")); 
229     }
230 
231     public void testAddUserAndVerify() throws IOException {
232         finishSetUp(m_testConfiguration);
233         connect();
234         login();
235 
236         sendCommand("adduser testAdd test");
237         assertTrue(getLastLine(readAnswer()).endsWith(" added")); 
238 
239         sendCommand("verify testNotAdded");
240         assertTrue(getLastLine(readAnswer()).endsWith(" does not exist"));
241 
242         sendCommand("verify testAdd");
243         assertTrue(getLastLine(readAnswer()).endsWith(" exists"));
244 
245         sendCommand("deluser testAdd");
246         readAnswer();
247 
248         sendCommand("verify testAdd");
249         assertTrue(getLastLine(readAnswer()).endsWith(" does not exist"));
250     }
251 
252     public void testDelUser() throws IOException {
253         finishSetUp(m_testConfiguration);
254         connect();
255         login();
256 
257         sendCommand("adduser testDel test");
258         assertTrue(getLastLine(readAnswer()).endsWith(" added")); 
259 
260         sendCommand("deluser testNotDeletable");
261         assertTrue(getLastLine(readAnswer()).endsWith(" doesn't exist"));
262 
263         sendCommand("verify testDel");
264         assertTrue(getLastLine(readAnswer()).endsWith(" exists"));
265 
266         sendCommand("deluser testDel");
267         assertTrue(getLastLine(readAnswer()).endsWith(" deleted"));
268 
269         sendCommand("verify testDel");
270         assertTrue(getLastLine(readAnswer()).endsWith(" does not exist"));
271     }
272 
273     public void testQuit() throws IOException {
274         int helpLines = 16;
275     
276         finishSetUp(m_testConfiguration);
277         connect();
278         login();
279 
280         sendCommand("help");
281         delay();
282         assertTrue("command line is effective", readAnswer().size() > 0);
283         readAnswer(helpLines);
284         
285         sendCommand("quit");
286         delay();
287         assertTrue("",readAnswer(1).contains("Bye"));
288 
289         sendCommand("help");
290         delay();
291         assertNull("connection is closed", m_reader.readLine());
292     }   
293 
294     public void testListUsers() throws IOException {
295         finishSetUp(m_testConfiguration);
296         connect();
297         login();
298 
299         String[] users = new String[] {"ccc", "aaa", "dddd", "bbbbb"};
300 
301         for (int i = 0; i < users.length; i++) {
302             String user = users[i];
303             sendCommand("adduser " + user + " test");
304             readAnswer(1);
305         }
306 
307         delay();
308 
309         sendCommand("listusers");
310         List list = readAnswer(5);
311 
312         assertEquals("user count line", "Existing accounts " + users.length, list.get(0));
313         
314         List readUserNames = new ArrayList();
315         for (Iterator iterator = list.iterator(); iterator.hasNext();) {
316             String answerLine = (String) iterator.next();
317             if (!answerLine.startsWith("user: ")) continue;
318             readUserNames.add(answerLine.substring(6));
319         }
320         assertEquals("user count", users.length, readUserNames.size());
321 
322         for (int i = 0; i < users.length; i++) {
323             String user = users[i];
324             assertTrue("name found", readUserNames.contains(user));
325         }
326     }
327 
328     private void delay() {
329         try {
330             Thread.sleep(100);
331         } catch (InterruptedException e) {
332             ; 
333         }
334     }
335 
336     public void testCommandCaseInsensitive() throws IOException {
337         finishSetUp(m_testConfiguration);
338         connect();
339         login();
340 
341         sendCommand("adduser testDel test");
342         assertTrue(getLastLine(readAnswer()).endsWith(" added")); 
343 
344         sendCommand("verify testDel");
345         assertTrue(getLastLine(readAnswer()).endsWith(" exists"));
346 
347         sendCommand("VERIFY testDel");
348         assertTrue(getLastLine(readAnswer()).endsWith(" exists"));
349 
350         sendCommand("vErIfY testDel");
351         assertTrue(getLastLine(readAnswer()).endsWith(" exists"));
352     }
353 
354     public void testParameterCaseSensitive() throws IOException {
355         finishSetUp(m_testConfiguration);
356         connect();
357         login();
358 
359         sendCommand("adduser testDel test");
360         assertTrue(getLastLine(readAnswer()).endsWith(" added")); 
361 
362         sendCommand("verify testDel");
363         assertTrue(getLastLine(readAnswer()).endsWith(" exists"));
364 
365         sendCommand("verify TESTDEL");
366         assertTrue(getLastLine(readAnswer()).endsWith(" does not exist"));
367 
368         sendCommand("verify testdel");
369         assertTrue(getLastLine(readAnswer()).endsWith(" does not exist"));
370     }
371 
372     public void testAlias() throws IOException {
373         m_mockUsersRepository.setForceUseJamesUser();
374         finishSetUp(m_testConfiguration);
375         connect();
376         login();
377         
378         
379         sendCommand("setalias testNonExist1 testNonExist2");
380         assertTrue(getLastLine(readAnswer()).equals("No such user testNonExist1"));
381 
382         sendCommand("adduser testAlias1 test");
383         assertTrue(getLastLine(readAnswer()).endsWith(" added"));
384 
385         sendCommand("showalias testAlias1");
386         assertTrue(getLastLine(readAnswer()).equals("User testAlias1 does not currently have an alias"));
387 
388         sendCommand("setalias testAlias1 testNonExist2");
389         assertTrue(getLastLine(readAnswer()).equals("Alias unknown to server - create that user first."));
390 
391         sendCommand("setalias testNonExist1 testAlias");
392         assertTrue(getLastLine(readAnswer()).equals("No such user testNonExist1"));
393 
394         sendCommand("adduser testAlias2 test");
395         assertTrue(getLastLine(readAnswer()).endsWith(" added"));
396 
397         
398         sendCommand("setalias testAlias1 testAlias2");
399         assertTrue(getLastLine(readAnswer()).equals("Alias for testAlias1 set to:testAlias2"));
400 
401         
402         sendCommand("setalias testAlias2 testAlias1");
403         assertTrue(getLastLine(readAnswer()).equals("Alias for testAlias2 set to:testAlias1"));
404 
405         
406         sendCommand("showalias testAlias1");
407         assertTrue(getLastLine(readAnswer()).equals("Current alias for testAlias1 is: testAlias2"));
408 
409         
410         sendCommand("setalias testAlias1 testAlias1");
411         assertTrue(getLastLine(readAnswer()).equals("Alias for testAlias1 set to:testAlias1"));
412 
413         sendCommand("adduser testAlias3 test");
414         assertTrue(getLastLine(readAnswer()).endsWith(" added"));
415 
416         
417         sendCommand("setalias testAlias1 testAlias3");
418         assertTrue(getLastLine(readAnswer()).equals("Alias for testAlias1 set to:testAlias3"));
419 
420         
421         sendCommand("showalias testAlias1");
422         assertTrue(getLastLine(readAnswer()).equals("Current alias for testAlias1 is: testAlias3"));
423 
424         
425         sendCommand("unsetalias testAlias1");
426         assertTrue(getLastLine(readAnswer()).equals("Alias for testAlias1 unset"));
427 
428         
429         sendCommand("showalias testAlias1");
430         assertTrue(getLastLine(readAnswer()).equals("User testAlias1 does not currently have an alias"));
431 
432     }
433 
434     public void testForward() throws IOException {
435         m_mockUsersRepository.setForceUseJamesUser();
436         finishSetUp(m_testConfiguration);
437         connect();
438         login();
439 
440         
441         sendCommand("setforwarding testNonExist1 testForward1@locahost");
442         assertTrue(getLastLine(readAnswer()).equals("No such user testNonExist1"));
443         
444         sendCommand("adduser testForwardUser test");
445         assertTrue(getLastLine(readAnswer()).endsWith(" added"));
446 
447         sendCommand("showforwarding testForwardUser");
448         assertTrue(getLastLine(readAnswer()).equals("User testForwardUser is not currently being forwarded"));
449 
450         sendCommand("setforwarding testForwardUser testForward1@locahost");
451         assertTrue(getLastLine(readAnswer()).equals("Forwarding destination for testForwardUser set to:testForward1@locahost"));
452         
453         
454         sendCommand("showforwarding testForwardUser");
455         assertTrue(getLastLine(readAnswer()).equals("Current forwarding destination for testForwardUser is: testForward1@locahost"));
456 
457         
458         sendCommand("setforwarding testForwardUser testForward2@locahost");
459         assertTrue(getLastLine(readAnswer()).equals("Forwarding destination for testForwardUser set to:testForward2@locahost"));
460 
461         
462         sendCommand("showforwarding testForwardUser");
463         assertTrue(getLastLine(readAnswer()).equals("Current forwarding destination for testForwardUser is: testForward2@locahost"));
464 
465         
466         sendCommand("unsetforwarding testForwardUser");
467         assertTrue(getLastLine(readAnswer()).equals("Forward for testForwardUser unset"));
468 
469         
470         sendCommand("showforwarding testForwardUser");
471         assertTrue(getLastLine(readAnswer()).equals("User testForwardUser is not currently being forwarded"));
472 
473     }
474 
475     public void testSetPassword() throws IOException {
476         finishSetUp(m_testConfiguration);
477         connect();
478         login();
479 
480         String lastLine;
481         
482         sendCommand("adduser testPwdUser pwd1");
483         lastLine = getLastLine(readAnswer());
484         assertTrue(lastLine.endsWith(" added"));
485 
486         assertTrue("initial password", m_mockUsersRepository.test("testPwdUser", "pwd1"));
487         
488         sendCommand("setpassword testPwdUser     ");
489         lastLine = getLastLine(readAnswer());
490         assertTrue("password changed to empty: "+lastLine, m_mockUsersRepository.test("testPwdUser", "pwd1"));
491 
492         
493         sendCommand("setpassword testPwdUser pwd2");
494         lastLine = getLastLine(readAnswer());
495         assertTrue("password not changed to pwd2: "+lastLine, m_mockUsersRepository.test("testPwdUser", "pwd2"));
496         
497         
498         sendCommand("setpassword testPwdUser pWD2");
499         lastLine = getLastLine(readAnswer());
500         assertFalse("password not changed to pWD2: "+lastLine, m_mockUsersRepository.test("testPwdUser", "pwd2"));
501         assertTrue("password not changed to pWD2: "+lastLine, m_mockUsersRepository.test("testPwdUser", "pWD2"));
502         
503     }
504     
505 }