001/* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, software 013 * distributed under the License is distributed on an "AS IS" BASIS, 014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 015 * See the License for the specific language governing permissions and 016 * limitations under the License. 017 */ 018package org.apache.hadoop.hbase.http.jmx; 019 020import static org.junit.Assert.assertEquals; 021import static org.junit.Assert.assertFalse; 022import static org.junit.Assert.assertTrue; 023 024import java.net.HttpURLConnection; 025import java.net.URL; 026import java.net.URLEncoder; 027import java.util.regex.Matcher; 028import java.util.regex.Pattern; 029import javax.servlet.http.HttpServletResponse; 030import org.apache.hadoop.hbase.HBaseClassTestRule; 031import org.apache.hadoop.hbase.http.HttpServer; 032import org.apache.hadoop.hbase.http.HttpServerFunctionalTest; 033import org.apache.hadoop.hbase.testclassification.MiscTests; 034import org.apache.hadoop.hbase.testclassification.SmallTests; 035import org.junit.AfterClass; 036import org.junit.BeforeClass; 037import org.junit.ClassRule; 038import org.junit.Test; 039import org.junit.experimental.categories.Category; 040import org.slf4j.Logger; 041import org.slf4j.LoggerFactory; 042 043@Category({ MiscTests.class, SmallTests.class }) 044public class TestJMXJsonServlet extends HttpServerFunctionalTest { 045 046 @ClassRule 047 public static final HBaseClassTestRule CLASS_RULE = 048 HBaseClassTestRule.forClass(TestJMXJsonServlet.class); 049 050 private static final Logger LOG = LoggerFactory.getLogger(TestJMXJsonServlet.class); 051 private static HttpServer server; 052 private static URL baseUrl; 053 054 @BeforeClass 055 public static void setup() throws Exception { 056 // Eclipse doesn't pick this up correctly from the plugin 057 // configuration in the pom. 058 System.setProperty(HttpServerFunctionalTest.TEST_BUILD_WEBAPPS, "target/test-classes/webapps"); 059 server = createTestServer(); 060 server.start(); 061 baseUrl = getServerURL(server); 062 } 063 064 @AfterClass 065 public static void cleanup() throws Exception { 066 server.stop(); 067 } 068 069 public static void assertReFind(String re, String value) { 070 Pattern p = Pattern.compile(re); 071 Matcher m = p.matcher(value); 072 assertTrue("'" + p + "' does not match " + value, m.find()); 073 } 074 075 public static void assertNotFind(String re, String value) { 076 Pattern p = Pattern.compile(re); 077 Matcher m = p.matcher(value); 078 assertFalse("'" + p + "' should not match " + value, m.find()); 079 } 080 081 @Test 082 public void testQuery() throws Exception { 083 String result = readOutput(new URL(baseUrl, "/jmx?qry=java.lang:type=Runtime")); 084 LOG.info("/jmx?qry=java.lang:type=Runtime RESULT: " + result); 085 assertReFind("\"name\"\\s*:\\s*\"java.lang:type=Runtime\"", result); 086 assertReFind("\"modelerType\"", result); 087 088 result = readOutput(new URL(baseUrl, "/jmx?qry=java.lang:type=Memory")); 089 LOG.info("/jmx?qry=java.lang:type=Memory RESULT: " + result); 090 assertReFind("\"name\"\\s*:\\s*\"java.lang:type=Memory\"", result); 091 assertReFind("\"modelerType\"", result); 092 093 result = readOutput(new URL(baseUrl, "/jmx")); 094 LOG.info("/jmx RESULT: " + result); 095 assertReFind("\"name\"\\s*:\\s*\"java.lang:type=Memory\"", result); 096 097 // test to get an attribute of a mbean 098 result = readOutput(new URL(baseUrl, "/jmx?get=java.lang:type=Memory::HeapMemoryUsage")); 099 LOG.info("/jmx RESULT: " + result); 100 assertReFind("\"name\"\\s*:\\s*\"java.lang:type=Memory\"", result); 101 assertReFind("\"committed\"\\s*:", result); 102 103 // negative test to get an attribute of a mbean 104 result = readOutput(new URL(baseUrl, "/jmx?get=java.lang:type=Memory::")); 105 LOG.info("/jmx RESULT: " + result); 106 assertReFind("\"ERROR\"", result); 107 108 // test to get JSONP result 109 result = readOutput(new URL(baseUrl, "/jmx?qry=java.lang:type=Memory&callback=mycallback1")); 110 LOG.info("/jmx?qry=java.lang:type=Memory&callback=mycallback RESULT: " + result); 111 assertReFind("^mycallback1\\(\\{", result); 112 assertReFind("\\}\\);$", result); 113 114 // negative test to get an attribute of a mbean as JSONP 115 result = readOutput(new URL(baseUrl, "/jmx?get=java.lang:type=Memory::&callback=mycallback2")); 116 LOG.info("/jmx RESULT: " + result); 117 assertReFind("^mycallback2\\(\\{", result); 118 assertReFind("\"ERROR\"", result); 119 assertReFind("\\}\\);$", result); 120 121 // test to get an attribute of a mbean as JSONP 122 result = readOutput( 123 new URL(baseUrl, "/jmx?get=java.lang:type=Memory::HeapMemoryUsage&callback=mycallback3")); 124 LOG.info("/jmx RESULT: " + result); 125 assertReFind("^mycallback3\\(\\{", result); 126 assertReFind("\"name\"\\s*:\\s*\"java.lang:type=Memory\"", result); 127 assertReFind("\"committed\"\\s*:", result); 128 assertReFind("\\}\\);$", result); 129 } 130 131 @Test 132 public void testGetPattern() throws Exception { 133 // test to get an attribute of a mbean as JSONP 134 String result = 135 readOutput(new URL(baseUrl, "/jmx?get=java.lang:type=Memory::[a-zA-z_]*NonHeapMemoryUsage")); 136 LOG.info("/jmx RESULT: " + result); 137 assertReFind("\"name\"\\s*:\\s*\"java.lang:type=Memory\"", result); 138 assertReFind("\"committed\"\\s*:", result); 139 assertReFind("\"NonHeapMemoryUsage\"\\s*:", result); 140 assertNotFind("\"HeapMemoryUsage\"\\s*:", result); 141 142 result = readOutput(new URL(baseUrl, "/jmx?get=java.lang:type=Memory::[^Non]*HeapMemoryUsage")); 143 LOG.info("/jmx RESULT: " + result); 144 assertReFind("\"name\"\\s*:\\s*\"java.lang:type=Memory\"", result); 145 assertReFind("\"committed\"\\s*:", result); 146 assertReFind("\"HeapMemoryUsage\"\\s*:", result); 147 assertNotFind("\"NonHeapHeapMemoryUsage\"\\s*:", result); 148 149 result = readOutput(new URL(baseUrl, 150 "/jmx?get=java.lang:type=Memory::[a-zA-z_]*HeapMemoryUsage,[a-zA-z_]*NonHeapMemoryUsage")); 151 LOG.info("/jmx RESULT: " + result); 152 assertReFind("\"name\"\\s*:\\s*\"java.lang:type=Memory\"", result); 153 assertReFind("\"committed\"\\s*:", result); 154 } 155 156 @Test 157 public void testPatternMatching() throws Exception { 158 assertReFind("[a-zA-z_]*Table1[a-zA-z_]*memStoreSize", 159 "Namespace_default_table_Table1_metric_memStoreSize"); 160 assertReFind("[a-zA-z_]*memStoreSize", "Namespace_default_table_Table1_metric_memStoreSize"); 161 } 162 163 @Test 164 public void testDisallowedJSONPCallback() throws Exception { 165 String callback = "function(){alert('bigproblems!')};foo"; 166 URL url = new URL(baseUrl, 167 "/jmx?qry=java.lang:type=Memory&callback=" + URLEncoder.encode(callback, "UTF-8")); 168 HttpURLConnection cnxn = (HttpURLConnection) url.openConnection(); 169 assertEquals(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, cnxn.getResponseCode()); 170 } 171 172 @Test 173 public void testUnderscoresInJSONPCallback() throws Exception { 174 String callback = "my_function"; 175 URL url = new URL(baseUrl, 176 "/jmx?qry=java.lang:type=Memory&callback=" + URLEncoder.encode(callback, "UTF-8")); 177 HttpURLConnection cnxn = (HttpURLConnection) url.openConnection(); 178 assertEquals(HttpServletResponse.SC_OK, cnxn.getResponseCode()); 179 } 180}