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, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  */
18 package org.apache.hadoop.mapreduce.v2.app.webapp;
19 
20 import static org.mockito.Mockito.*;
21 
22 import java.io.IOException;
23 import java.util.Iterator;
24 
25 import org.apache.commons.lang.StringUtils;
26 import org.apache.hadoop.conf.Configuration;
27 import org.apache.hadoop.mapreduce.JobACL;
28 import org.apache.hadoop.mapreduce.v2.api.records.JobId;
29 import org.apache.hadoop.mapreduce.v2.api.records.TaskId;
30 import org.apache.hadoop.mapreduce.v2.app.AppContext;
31 import org.apache.hadoop.mapreduce.v2.app.job.Job;
32 import org.apache.hadoop.mapreduce.v2.app.job.Task;
33 import org.apache.hadoop.mapreduce.v2.util.MRApps;
34 import org.apache.hadoop.security.UserGroupInformation;
35 import org.apache.hadoop.yarn.api.records.ApplicationId;
36 import org.apache.hadoop.yarn.webapp.Controller.RequestContext;
37 import org.apache.hadoop.yarn.webapp.MimeType;
38 import org.apache.hadoop.yarn.webapp.ResponseInfo;
39 import org.junit.Before;
40 import org.junit.Test;
41 import static org.junit.Assert.*;
42 
43 public class TestAppController {
44 
45   private AppControllerForTest appController;
46   private RequestContext ctx;
47   private Job job;
48 
49   @Before
setUp()50   public void setUp() throws IOException {
51     AppContext context = mock(AppContext.class);
52     when(context.getApplicationID()).thenReturn(
53         ApplicationId.newInstance(0, 0));
54     when(context.getApplicationName()).thenReturn("AppName");
55     when(context.getUser()).thenReturn("User");
56     when(context.getStartTime()).thenReturn(System.currentTimeMillis());
57     job = mock(Job.class);
58     Task task = mock(Task.class);
59 
60     when(job.getTask(any(TaskId.class))).thenReturn(task);
61 
62     JobId jobID = MRApps.toJobID("job_01_01");
63     when(context.getJob(jobID)).thenReturn(job);
64     when(job.checkAccess(any(UserGroupInformation.class), any(JobACL.class)))
65         .thenReturn(true);
66 
67     App app = new App(context);
68     Configuration configuration = new Configuration();
69     ctx = mock(RequestContext.class);
70 
71     appController = new AppControllerForTest(app, configuration, ctx);
72     appController.getProperty().put(AMParams.JOB_ID, "job_01_01");
73     appController.getProperty().put(AMParams.TASK_ID, "task_01_01_m01_01");
74 
75   }
76 
77   /**
78    * test bad request should be status 400...
79    */
80   @Test
testBadRequest()81   public void testBadRequest() {
82     String message = "test string";
83     appController.badRequest(message);
84     verifyExpectations(message);
85   }
86 
87   @Test
testBadRequestWithNullMessage()88   public void testBadRequestWithNullMessage() {
89     // It should not throw NullPointerException
90     appController.badRequest(null);
91     verifyExpectations(StringUtils.EMPTY);
92   }
93 
verifyExpectations(String message)94   private void verifyExpectations(String message) {
95     verify(ctx).setStatus(400);
96     assertEquals("application_0_0000", appController.getProperty()
97         .get("app.id"));
98     assertNotNull(appController.getProperty().get("rm.web"));
99     assertEquals("Bad request: " + message,
100         appController.getProperty().get("title"));
101   }
102 
103   /**
104    * Test the method 'info'.
105    */
106   @Test
testInfo()107   public void testInfo() {
108 
109     appController.info();
110     Iterator<ResponseInfo.Item> iterator = appController.getResponseInfo()
111         .iterator();
112     ResponseInfo.Item item = iterator.next();
113     assertEquals("Application ID:", item.key);
114     assertEquals("application_0_0000", item.value);
115     item = iterator.next();
116     assertEquals("Application Name:", item.key);
117     assertEquals("AppName", item.value);
118     item = iterator.next();
119     assertEquals("User:", item.key);
120     assertEquals("User", item.value);
121 
122     item = iterator.next();
123     assertEquals("Started on:", item.key);
124     item = iterator.next();
125     assertEquals("Elasped: ", item.key);
126 
127   }
128 
129   /**
130    *  Test method 'job'. Should print message about error or set JobPage class for rendering
131    */
132   @Test
testGetJob()133   public void testGetJob() {
134     when(job.checkAccess(any(UserGroupInformation.class), any(JobACL.class)))
135         .thenReturn(false);
136 
137     appController.job();
138     verify(appController.response()).setContentType(MimeType.TEXT);
139     assertEquals(
140         "Access denied: User user does not have permission to view job job_01_01",
141         appController.getData());
142     when(job.checkAccess(any(UserGroupInformation.class), any(JobACL.class)))
143         .thenReturn(true);
144 
145     appController.getProperty().remove(AMParams.JOB_ID);
146     appController.job();
147     assertEquals(
148         "Access denied: User user does not have permission to view job job_01_01Bad Request: Missing job ID",
149         appController.getData());
150 
151     appController.getProperty().put(AMParams.JOB_ID, "job_01_01");
152     appController.job();
153     assertEquals(JobPage.class, appController.getClazz());
154   }
155 
156   /**
157    *  Test method 'jobCounters'. Should print message about error or set CountersPage class for rendering
158    */
159   @Test
testGetJobCounters()160   public void testGetJobCounters() {
161 
162     when(job.checkAccess(any(UserGroupInformation.class), any(JobACL.class)))
163         .thenReturn(false);
164 
165     appController.jobCounters();
166     verify(appController.response()).setContentType(MimeType.TEXT);
167     assertEquals(
168         "Access denied: User user does not have permission to view job job_01_01",
169         appController.getData());
170     when(job.checkAccess(any(UserGroupInformation.class), any(JobACL.class)))
171         .thenReturn(true);
172 
173     appController.getProperty().remove(AMParams.JOB_ID);
174     appController.jobCounters();
175     assertEquals(
176         "Access denied: User user does not have permission to view job job_01_01Bad Request: Missing job ID",
177         appController.getData());
178 
179     appController.getProperty().put(AMParams.JOB_ID, "job_01_01");
180     appController.jobCounters();
181     assertEquals(CountersPage.class, appController.getClazz());
182   }
183 
184   /**
185    *  Test method 'taskCounters'. Should print message about error or set CountersPage class for rendering
186    */
187   @Test
testGetTaskCounters()188   public void testGetTaskCounters() {
189 
190     when(job.checkAccess(any(UserGroupInformation.class), any(JobACL.class)))
191         .thenReturn(false);
192 
193     appController.taskCounters();
194     verify(appController.response()).setContentType(MimeType.TEXT);
195     assertEquals(
196         "Access denied: User user does not have permission to view job job_01_01",
197         appController.getData());
198 
199     when(job.checkAccess(any(UserGroupInformation.class), any(JobACL.class)))
200         .thenReturn(true);
201 
202     appController.getProperty().remove(AMParams.TASK_ID);
203     appController.taskCounters();
204     assertEquals(
205         "Access denied: User user does not have permission to view job job_01_01missing task ID",
206         appController.getData());
207 
208     appController.getProperty().put(AMParams.TASK_ID, "task_01_01_m01_01");
209     appController.taskCounters();
210     assertEquals(CountersPage.class, appController.getClazz());
211   }
212   /**
213    *  Test method 'singleJobCounter'. Should set SingleCounterPage class for rendering
214    */
215 
216   @Test
testGetSingleJobCounter()217   public void testGetSingleJobCounter() throws IOException {
218     appController.singleJobCounter();
219     assertEquals(SingleCounterPage.class, appController.getClazz());
220   }
221 
222   /**
223    *  Test method 'singleTaskCounter'. Should set SingleCounterPage class for rendering
224    */
225   @Test
testGetSingleTaskCounter()226   public void testGetSingleTaskCounter() throws IOException {
227     appController.singleTaskCounter();
228     assertEquals(SingleCounterPage.class, appController.getClazz());
229     assertNotNull(appController.getProperty().get(AppController.COUNTER_GROUP));
230     assertNotNull(appController.getProperty().get(AppController.COUNTER_NAME));
231   }
232   /**
233    *  Test method 'tasks'. Should set TasksPage class for rendering
234    */
235 
236   @Test
testTasks()237   public void testTasks() {
238 
239     appController.tasks();
240 
241     assertEquals(TasksPage.class, appController.getClazz());
242   }
243   /**
244    *  Test method 'task'. Should set TaskPage class for rendering and information for title
245    */
246   @Test
testTask()247   public void testTask() {
248 
249     appController.task();
250     assertEquals("Attempts for task_01_01_m01_01" ,
251         appController.getProperty().get("title"));
252 
253     assertEquals(TaskPage.class, appController.getClazz());
254   }
255 
256   /**
257    *   Test method 'conf'. Should set JobConfPage class for rendering
258    */
259   @Test
testConfiguration()260   public void testConfiguration() {
261 
262     appController.conf();
263 
264     assertEquals(JobConfPage.class, appController.getClazz());
265   }
266 
267   /**
268    *   Test method 'conf'. Should set AttemptsPage class for rendering or print information about error
269    */
270   @Test
testAttempts()271   public void testAttempts() {
272 
273     appController.getProperty().remove(AMParams.TASK_TYPE);
274 
275     when(job.checkAccess(any(UserGroupInformation.class), any(JobACL.class)))
276         .thenReturn(false);
277 
278     appController.attempts();
279     verify(appController.response()).setContentType(MimeType.TEXT);
280     assertEquals(
281         "Access denied: User user does not have permission to view job job_01_01",
282         appController.getData());
283 
284     when(job.checkAccess(any(UserGroupInformation.class), any(JobACL.class)))
285         .thenReturn(true);
286 
287     appController.getProperty().remove(AMParams.TASK_ID);
288     appController.attempts();
289     assertEquals(
290         "Access denied: User user does not have permission to view job job_01_01",
291         appController.getData());
292 
293     appController.getProperty().put(AMParams.TASK_ID, "task_01_01_m01_01");
294     appController.attempts();
295     assertEquals("Bad request: missing task-type.", appController.getProperty()
296         .get("title"));
297     appController.getProperty().put(AMParams.TASK_TYPE, "m");
298 
299     appController.attempts();
300     assertEquals("Bad request: missing attempt-state.", appController
301         .getProperty().get("title"));
302     appController.getProperty().put(AMParams.ATTEMPT_STATE, "State");
303 
304     appController.attempts();
305 
306     assertEquals(AttemptsPage.class, appController.getClazz());
307   }
308 
309 }
310