blob: 6672f0eb9ba85918673a525bda568163c4fcd997 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.hadoop.chukwa.database;
import junit.framework.*;
import java.util.*;
import java.text.*;
import java.io.*;
import java.net.URL;
import java.sql.*;
import org.apache.commons.httpclient.*;
import org.apache.commons.httpclient.methods.*;
import org.apache.commons.httpclient.params.HttpMethodParams;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import org.json.simple.JSONValue;
import org.mortbay.jetty.Server;
import org.mortbay.xml.XmlConfiguration;
import org.apache.hadoop.chukwa.util.*;
/*
* Testing the JSON output from the website with the database result.
*
*/
public class TestDatabaseWebJson extends TestCase {
protected HashMap testTables;
protected String data_url="http://localhost:8080/hicc/jsp/get_db_data.jsp";
private Server server = null;
private Log log = LogFactory.getLog(TestDatabaseWebJson.class);
/*
* setup list of tables to do testing.
* Add the table name and the table's primary keys.
*/
protected void setUp() {
testTables = new HashMap();
ArrayList<String> keys = new ArrayList<String>();
keys.add("timestamp");
keys.add("mount");
testTables.put("cluster_disk", keys);
keys = new ArrayList<String>();
keys.add("timestamp");
testTables.put("cluster_system_metrics", keys);
keys = new ArrayList<String>();
keys.add("timestamp");
keys.add("host");
keys.add("mount");
testTables.put("disk", keys);
keys = new ArrayList<String>();
keys.add("job_id");
testTables.put("mr_job", keys);
keys = new ArrayList<String>();
keys.add("task_id");
testTables.put("mr_task", keys);
keys = new ArrayList<String>();
keys.add("timestamp");
testTables.put("system_metrics", keys);
URL serverConf = TestDatabaseWebJson.class
.getResource("/WEB-INF/jetty.xml");
server = new Server();
XmlConfiguration configuration;
try {
configuration = new XmlConfiguration(serverConf);
configuration.configure(server);
server.start();
server.setStopAtShutdown(true);
} catch (Exception e) {
log.error(ExceptionUtil.getStackTrace(e));
}
}
protected void tearDown() {
try {
server.stop();
Thread.sleep(2000);
} catch (Exception e) {
log.error(ExceptionUtil.getStackTrace(e));
}
}
/*
* similar to PHP join function to join a string array to one single string.
* for example, if the token is "," and the strings array is ('a','b','c')
* the final result will be "a,b,c"
*
* @param token The separator which join the strings together
* @param strings list of strings which we want to merge together
* @return final string which merge together.
*/
protected static String join( String token, ArrayList<String> strings )
{
StringBuffer sb = new StringBuffer();
for( int x = 0; x < ( strings.size() - 1 ); x++ ) {
sb.append( strings.get(x) );
sb.append( token );
}
sb.append( strings.get( strings.size() - 1 ) );
return( sb.toString() );
}
/*
* format the query string for the database testing. Select the
* primary key value from the json object.
*
* @param tableName The name of the database table to build the query on.
* @param jo JSON object which contain the primary key of the row which we
* want to test.
* @return the actual database query string for the row selection.
*/
protected String getDatabaseQuery(String tableName, JSONObject jo) {
ArrayList<String> keys = (ArrayList<String>)testTables.get(tableName);
ArrayList<String> criterias = new ArrayList<String>();
Iterator i = keys.iterator();
while (i.hasNext()) {
String key=(String)i.next();
try {
String value=(String)jo.get(key);
if (key.compareToIgnoreCase("timestamp")==0) {
value=DatabaseWriter.formatTimeStamp(Long.parseLong(value));
}
String c=key+"=\""+value+"\"";
criterias.add(c);
} catch (Exception e) {
System.out.println("Cannot get value for key: "+key);
}
}
String criteria=join(" and ", criterias);
String query="select * from ["+tableName+"] where "+criteria;
return query;
}
/*
* the function will do the actual table verification. If will first
* get the result from the website JSON object. Then it will compare the
* JSON object with the values in the database.
*
* @param table name of the table to be verified.
*/
protected void verifyTableData(String table) {
Calendar startCalendar = new GregorianCalendar();
// startCalendar.add(Calendar.HOUR_OF_DAY,-1);
startCalendar.add(Calendar.MINUTE, -30);
long startTime=startCalendar.getTime().getTime();
Calendar endCalendar = new GregorianCalendar();
// endCalendar.add(Calendar.HOUR_OF_DAY,1);
long endTime=endCalendar.getTime().getTime();
String url=data_url+"?table="+table+"&start="+startTime+"&end="+endTime;
System.out.println(url);
HttpClient client = new HttpClient();
GetMethod method = new GetMethod(url);
try {
/*
* 1. get the json result for the specified table
*/
int statusCode = client.executeMethod(method);
if (statusCode != HttpStatus.SC_OK) {
System.out.println("Http Error: "+method.getStatusLine());
}
BufferedReader reader = new BufferedReader(new InputStreamReader( method.getResponseBodyAsStream(),
method.getResponseCharSet()));
String json_str="";
String str;
while ((str = reader.readLine()) != null) {
json_str+=str;
}
/*
* 2. convert the json string to individual field and compare it
* with the database
*/
String cluster = "demo";
DatabaseWriter db = new DatabaseWriter(cluster);
JSONArray json_array=(JSONArray)JSONValue.parse(json_str);
for (int i=0; i < json_array.size(); i++) {
JSONObject row_obj=(JSONObject) json_array.get(i);
// get the database row
String queryString=getDatabaseQuery(table, row_obj);
Macro m=new Macro(startTime, endTime, queryString);
ResultSet rs = db.query(m.toString());
// move to the first record
rs.next();
ResultSetMetaData md=rs.getMetaData();
Iterator names=row_obj.keySet().iterator();
while (names.hasNext()) {
String name=(String)names.next();
String jsonValue=(String)row_obj.get(name);
String dbValue=rs.getString(name);
int dbCol=rs.findColumn(name);
int dbType=md.getColumnType(dbCol);
if (dbType==93) {
// timestamp
dbValue=Long.toString(rs.getTimestamp(name).getTime());
}
// System.out.println("compare "+name+":"+dbType+":"+dbValue+":"+jsonValue);
assertEquals(dbValue, jsonValue);
}
}
db.close();
} catch (SQLException e) {
System.out.println("Exception: "+e.toString()+":"+e.getMessage());
System.out.println("Exception: "+e.toString()+":"+e.getSQLState());
System.out.println("Exception: "+e.toString()+":"+e.getErrorCode());
fail("SQL Error:"+ExceptionUtil.getStackTrace(e));
} catch (Exception eOther) {
System.out.println("Other Exception: "+eOther.toString());
eOther.printStackTrace();
fail("Error:"+ExceptionUtil.getStackTrace(eOther));
} finally {
}
}
/*
* Perform the actual testing. It will get the result from the web URL first.
* Then it will get the result from the database and compare it.
*/
public void testJsonResult() {
Iterator i=testTables.keySet().iterator();
while (i.hasNext()) {
String tableName=(String)i.next();
verifyTableData(tableName);
}
}
}