package com.aliyun.openservices.log.functiontest;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.aliyun.openservices.log.Client;
import com.aliyun.openservices.log.common.*;
import com.aliyun.openservices.log.common.Consts.CompressType;
import com.aliyun.openservices.log.common.Consts.CursorMode;
import com.aliyun.openservices.log.exception.LogException;
import com.aliyun.openservices.log.functiontest.others.Credentials;
import com.aliyun.openservices.log.http.client.HttpMethod;
import com.aliyun.openservices.log.http.comm.ResponseMessage;
import com.aliyun.openservices.log.request.*;
import com.aliyun.openservices.log.response.*;
import com.aliyun.openservices.log.util.LZ4Encoder;
import org.junit.Test;

import java.io.*;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.URI;
import java.util.*;

import static org.junit.Assert.*;

/**
 * java sdk unittest
 *
 * @author bozhi.ch
 */
public class SlsClientUnitTest {

    private static final Credentials credentials = Credentials.load();
    private static final String TEST_ACCESS_KEY_ID = credentials.getAccessKeyId();
    private static final String TEST_ACCESS_KEY = credentials.getAccessKey();

    private SlsClientMock logClientMock = new SlsClientMock();
    private SlsClientMockSend mock = new SlsClientMockSend("http://mock-sls.aliyun-inc.com",
            TEST_ACCESS_KEY_ID,
            TEST_ACCESS_KEY);


    @Test
    public void TestExtractResponseMessage() {
        // / normal case
        JSONArray jObj_1 = JSONArray
                .parseArray(SlsClientTestData.TEST_LOGS_1);
        Map<String, String> headers = new HashMap<String, String>();
        headers.put(Consts.CONST_X_SLS_PROCESS, Consts.CONST_RESULT_INCOMPLETE);
        GetLogsResponse response_1 = new GetLogsResponse(headers);
        logClientMock.ExtractLogs(response_1, jObj_1);
        // assertEquals(100, meta.mTotalogNum);
        assertEquals(response_1.GetCount(), 1);
        assertEquals(response_1.IsCompleted(), false);
        List<QueriedLog> logs_1 = response_1.getLogs();
        assertEquals(logs_1.size(), 1);
        QueriedLog queriedLog = logs_1.get(0);
        LogItem logItem = queriedLog.GetLogItem();
        assertEquals(logItem.mLogTime, 100);
        assertEquals(queriedLog.mSource, "10.10.10.10");
        ArrayList<LogContent> contents = logItem.mContents;
        assertEquals(contents.size(), 2);
        assertEquals(contents.get(0).mKey, "key_1");
        assertEquals(contents.get(0).mValue, "value_1");
        assertEquals(contents.get(1).mKey, "key_2");
        assertEquals(contents.get(1).mValue, "value_2");

        JSONArray jObj_2 = JSONArray
                .parseArray(SlsClientTestData.TEST_LOGS_2);
        headers = new HashMap<String, String>();
        headers.put(Consts.CONST_X_SLS_PROCESS, Consts.CONST_RESULT_COMPLETE);
        GetLogsResponse response_2 = new GetLogsResponse(headers);
        logClientMock.ExtractLogs(response_2, jObj_2);
        // assertEquals(100, meta.mTotalogNum);
        assertEquals(response_2.GetCount(), 2);
        assertEquals(response_2.IsCompleted(), true);
        List<QueriedLog> logs_2 = response_2.getLogs();
        assertEquals(logs_2.size(), 2);
        queriedLog = logs_2.get(0);
        logItem = queriedLog.GetLogItem();
        assertEquals(logItem.mLogTime, 100);
        assertEquals(queriedLog.mSource, "10.10.10.10");
        contents = logItem.mContents;
        assertEquals(contents.size(), 2);
        assertEquals(contents.get(0).mKey, "key_1");
        assertEquals(contents.get(0).mValue, "value_1");
        assertEquals(contents.get(1).mKey, "key_2");
        assertEquals(contents.get(1).mValue, "value_2");

        queriedLog = logs_2.get(1);
        logItem = queriedLog.GetLogItem();
        assertEquals(logItem.mLogTime, 200);
        assertEquals(queriedLog.mSource, "20.20.20.20");
        contents = logItem.mContents;
        assertEquals(contents.size(), 2);
        assertEquals(contents.get(0).mKey, "key_3");
        assertEquals(contents.get(0).mValue, "value_3");
        assertEquals(contents.get(1).mKey, "key_4");
        assertEquals(contents.get(1).mValue, "value_4");
    }

    @Test
    public void TestParserResponseMessage() {

        // the content of ResponseMessage is null
        ResponseMessage message = new ResponseMessage();
        try {
            logClientMock.ParserResponseMessage(message);
        } catch (Exception e) {
            if (e instanceof LogException) {
                assertEquals("BadResponse", ((LogException) e).GetErrorCode());
            } else {
                assertTrue(e.getMessage(), false);
            }
        }

        // read the content of ResponseMessage error
        message.setContent(new InputStream() {
            @Override
            public int read() throws IOException {
                throw new IOException();
            }

        });
        try {
            logClientMock.ParserResponseMessage(message);
        } catch (Exception e) {
            if (e instanceof LogException) {
                assertEquals("BadResponse",
                        ((LogException) e).GetErrorCode());
                // assertTrue(((LogException)e).getMessage().contains("Io exception"));
            } else {
                assertTrue(e.getMessage(), false);
            }
        }

        // the content is an illegal json string
        message.setContent(new ByteArrayInputStream(
                Hex2Byte(SlsClientTestData.TEST_LIST_TOPIC_HEX.substring(1))));
        try {
            logClientMock.ParserResponseMessage(message);
        } catch (Exception e) {
            if (e instanceof LogException) {
                assertEquals("BadResponse",
                        ((LogException) e).GetErrorCode());
                // assertTrue(((LogException)e).getMessage().contains("not valid json string"));
            } else {
                assertTrue(e.getMessage(), false);
            }
        }

        // normal case
        message.setContent(new ByteArrayInputStream(
                Hex2Byte(SlsClientTestData.TEST_LIST_TOPIC_HEX)));
        message.SetBody(Hex2Byte(SlsClientTestData.TEST_LIST_TOPIC_HEX));
        try {
            JSONObject jObj = logClientMock.ParserResponseMessage(message);
            assertEquals("{\"ListTopic\":[\"Topic1\",\"Topic2\"]}",
                    jObj.toString());
        } catch (Exception e) {
            assertTrue(e.getMessage(), false);
        }
    }

    @Test
    public void TestExtractConfigs() {
        JSONArray array = new JSONArray();
        array.add("testconfig1");

        JSONObject testObj = new JSONObject();
        testObj.put("configs", array);

        try {
            List<String> res = logClientMock.ExtractConfigs(testObj, "");

            assertEquals("configNum does not match", array.size(), res.size());
            for (int i = 0; i < array.size(); i++) {
                assertEquals("config name does not match", array.getString(i), res.get(i));
            }

        } catch (LogException e) {
            assertTrue(e.getMessage(), false);
        }
    }

    @Test
    public void TestExtractMachineGroups() {
        JSONArray array = new JSONArray();
        array.add("testmachinegroup1");

        JSONObject testObj = new JSONObject();
        testObj.put("machinegroups", array);

        try {
            List<String> res = logClientMock.ExtractMachineGroups(testObj, "");

            assertEquals("machineGroupNum does not match", array.size(), res.size());
            for (int i = 0; i < array.size(); i++) {
                assertEquals("group name does not match", array.getString(i), res.get(i));
            }

        } catch (Exception e) {
            assertTrue(e.getMessage(), false);
        }
    }

    @Test
    public void TestExtractConfigFromResponse() {
        JSONObject jObj = new JSONObject();
        jObj.put("configName", "testconfig");
        jObj.put("inputType", "file");

        JSONObject inputDetail = new JSONObject();
        inputDetail.put("logType", "common_reg_log");
        inputDetail.put("logPath", "/var/log/httpd/");
        inputDetail.put("filePattern", "access.log");
        inputDetail.put("localStorage", true);
        inputDetail.put("timeFormat", "test1");
        inputDetail.put("logBeginRegex", "test2");
        inputDetail.put("regex", "test3");
        inputDetail.put("topicFormat", "none");

        JSONArray key = new JSONArray();
        key.add("name");
        key.add("seqno");
        inputDetail.put("key", key);

        JSONArray filterRegex = new JSONArray();
        filterRegex.add("x1");
        filterRegex.add("x2");
        inputDetail.put("filterRegex", filterRegex);

        JSONArray filterKey = new JSONArray();
        filterKey.add("x3");
        filterKey.add("x4");
        inputDetail.put("filterKey", filterKey);

        jObj.put("inputDetail", inputDetail);

        jObj.put("outputType", "loghub");

        JSONObject outputDetail = new JSONObject();
        outputDetail.put("projectName", "ay42");
        outputDetail.put("logstoreName", "perfcounter");
        jObj.put("outputDetail", outputDetail);

        jObj.put("createTime", 12343235);
        jObj.put("lastModifyTime", 12343234);

        Config config = null;
        try {
            config = logClientMock.ExtractConfigFromResponse(jObj, "");
        } catch (LogException e) {
            assertTrue(e.getMessage(), false);
        }

        assertEquals(config.GetConfigName(), "testconfig");

        assertEquals(((ConfigInputDetail) (config.GetInputDetail())).GetLogType(), inputDetail.getString("logType"));
        assertEquals(((ConfigInputDetail) (config.GetInputDetail())).GetLogPath(), inputDetail.getString("logPath"));
        assertEquals(((ConfigInputDetail) (config.GetInputDetail())).GetFilePattern(), inputDetail.getString("filePattern"));
        assertEquals(config.GetInputDetail().GetLocalStorage(), inputDetail.getBoolean("localStorage"));
        assertEquals(((ConfigInputDetail) (config.GetInputDetail())).GetTimeFormat(), inputDetail.getString("timeFormat"));
        assertEquals(((ConfigInputDetail) (config.GetInputDetail())).GetLogBeginRegex(), inputDetail.getString("logBeginRegex"));
        assertEquals(((ConfigInputDetail) (config.GetInputDetail())).GetRegex(), inputDetail.getString("regex"));
        assertEquals(((ConfigInputDetail) (config.GetInputDetail())).GetTopicFormat(), inputDetail.getString("topicFormat"));

        List<String> keyList = ((ConfigInputDetail) (config.GetInputDetail())).GetKey();
        assertEquals(keyList.size(), key.size());
        for (int i = 0; i < keyList.size(); i++) {
            assertEquals(keyList.get(i), key.getString(i));
        }

        List<String> filterRegexList = config.GetInputDetail().GetFilterRegex();
        assertEquals(filterRegexList.size(), filterRegex.size());
        for (int i = 0; i < filterRegexList.size(); i++) {
            assertEquals(filterRegexList.get(i), filterRegex.getString(i));
        }

        List<String> filterKeyList = config.GetInputDetail().GetFilterKey();
        assertEquals(filterKeyList.size(), filterKey.size());
        for (int i = 0; i < filterKeyList.size(); i++) {
            assertEquals(filterKeyList.get(i), filterKey.getString(i));
        }


        assertEquals(false, outputDetail.containsKey("endpoint"));
        assertEquals(config.GetOutputDetail().GetLogstoreName(), outputDetail.getString("logstoreName"));

        assertEquals(config.GetCreateTime(), 12343235);
        assertEquals(config.GetLastModifyTime(), 12343234);
    }

    @Test
    public void TestExtractMachineGroupFromResponse() {
        JSONObject jObj = new JSONObject();
        jObj.put("groupName", "testgroup");
        jObj.put("groupType", "");
        jObj.put("machineIdentifyType", "uuid");

        JSONObject groupAttribute = new JSONObject();
        groupAttribute.put("externalName", "testgroupX");
        groupAttribute.put("groupTopic", "topic");
        jObj.put("groupAttribute", groupAttribute);

        JSONArray machineList = new JSONArray();
        String machine1 = "uu94ff0127x";
        String machine2 = "uu14ff0127y";
        machineList.add(machine1);
        machineList.add(machine2);
        jObj.put("machineList", machineList);

        jObj.put("createTime", 12343235);
        jObj.put("lastModifyTime", 12343234);

        MachineGroup group = null;
        try {
            group = logClientMock.ExtractMachineGroupFromResponse(jObj, "");
        } catch (LogException e) {
            fail(e.getMessage());
        }

        assertEquals(group.GetGroupName(), "testgroup");
        assertEquals(group.GetGroupType(), "");
        assertEquals(group.GetMachineIdentifyType(), "uuid");
        assertEquals(group.GetExternalName(), "testgroupX");
        assertEquals(group.GetGroupTopic(), "topic");

        assertEquals(group.GetMachineList().size(), machineList.size());
        for (int i = 0; i < group.GetMachineList().size(); i++) {
            assertEquals(group.GetMachineList().get(i), machineList.getString(i));
        }

        assertEquals(group.GetCreateTime(), 12343235);
        assertEquals(group.GetLastModifyTime(), 12343234);
    }

    @Test
    public void TestParseResponseMessage() {
        ResponseMessage response = new ResponseMessage();

        byte[] testBytes = null;
        try {
            testBytes = SlsClientTestData.TEST_RESPONSE_RAW_DATA.getBytes("utf-8");
        } catch (UnsupportedEncodingException e) {
            fail(e.getMessage());
        }

        response.setContent(new ByteArrayInputStream(testBytes));
        response.SetBody(testBytes);
        try {
            JSONObject origin = JSONObject.parseObject(SlsClientTestData.TEST_RESPONSE_RAW_DATA);
            JSONObject result = logClientMock.ParserResponseMessage(response, "");

            assertEquals(result.getString("projectName"), origin.getString("projectName"));
            assertEquals(result.getString("projectDesc"), origin.getString("projectDesc"));
            assertEquals(result.getString("projectStatus"), origin.getString("projectStatus"));
            assertEquals(result.getJSONObject("quota").getIntValue("logStream"), origin.getJSONObject("quota").getIntValue("logStream"));
            assertEquals(result.getJSONObject("quota").getIntValue("shard"), origin.getJSONObject("quota").getIntValue("shard"));
            assertEquals(result.getIntValue("createTime"), origin.getIntValue("createTime"));
            assertEquals(result.getIntValue("lastModifyTime"), origin.getIntValue("lastModifyTime"));

        } catch (Exception e) {
            fail(e.getMessage());
        }
    }

    @Test
    public void TestParseResponseMessageToArray() {
        ResponseMessage response = new ResponseMessage();

        byte[] testBytes = null;
        try {
            testBytes = SlsClientTestData.TEST_RESPONSE_RAW_ARRAY.getBytes("utf-8");
        } catch (UnsupportedEncodingException e) {
            fail(e.getMessage());
        }

        response.setContent(new ByteArrayInputStream(testBytes));
        response.SetBody(testBytes);
        try {
            JSONArray origin = JSONArray.parseArray(SlsClientTestData.TEST_RESPONSE_RAW_ARRAY);
            JSONArray result = logClientMock.ParseResponseMessageToArray(response, "");
            assertEquals(origin.size(), result.size());

            for (int i = 0; i < origin.size(); i++) {
                String shardStatusOrigin = origin.getJSONObject(i).getString("shardStatus");
                String shardStatusResult = result.getJSONObject(i).getString("shardStatus");
                int shardIdOrigin = origin.getJSONObject(i).getIntValue("shardID");
                int shardIdResult = result.getJSONObject(i).getIntValue("shardID");
                assertEquals(shardStatusOrigin, shardStatusResult);
                assertEquals(shardIdOrigin, shardIdResult);
            }

        } catch (Exception e) {
            fail(e.getMessage());
        }
    }

    @Test
    public void TestCreateConfig() {
        ResponseMessage response = new ResponseMessage();

        Map<String, String> resHeaders = new HashMap<String, String>();
        resHeaders.put(Consts.CONST_X_SLS_REQUESTID, "TESTREQID");
        response.setHeaders(resHeaders);
        response.setStatusCode(200);

        String testConfigName = "test_config";
        Config config = new Config(testConfigName);
        ConfigInputDetail inputDetail = new ConfigInputDetail();
        inputDetail.SetLogType("common_reg_log");
        inputDetail.SetLogPath("/var/log/httpd/");
        inputDetail.SetFilePattern("access.log");
        inputDetail.SetLocalStorage(true);
        inputDetail.SetTimeFormat("%H%m%S");
        inputDetail.SetLogBeginRegex("\\d+");
        inputDetail.SetRegex("(\\d+) (\\d+)");
        inputDetail.SetTopicFormat("none");

        ArrayList<String> key = new ArrayList<String>();
        key.add("number");
        key.add("seqno");
        inputDetail.SetKey(key);

        ArrayList<String> filterKey = new ArrayList<String>();
        filterKey.add("number1");
        filterKey.add("seqno1");


        ArrayList<String> filterRegex = new ArrayList<String>();
        filterRegex.add("num-123*");
        filterRegex.add("seq-abc*");
        inputDetail.SetFilterKeyRegex(filterKey, filterRegex);

        config.SetInputDetail(inputDetail);

        ConfigOutputDetail outputDetail = new ConfigOutputDetail();

        outputDetail.SetEndpoint("ay42");
        outputDetail.SetLogstoreName("perfcounter");
        outputDetail.SetCompressType("lz4");
        config.SetOutputDetail(outputDetail);

        String project = "test-project";

        try {
            mock.ChangeResponse(response);
            mock.CreateConfig(project, config);
        } catch (LogException e) {
            fail(e.getMessage());
        }

        byte[] errorBody = null;
        try {
            errorBody = SlsClientTestData.TEST_STANDARD_ERROR.getBytes("utf-8");
        } catch (UnsupportedEncodingException e) {
            fail(e.getMessage());
        }
        InputStream errorContent = new ByteArrayInputStream(errorBody);
        response.setStatusCode(400);
        response.setContent(errorContent);
        mock.ChangeResponse(response);
        try {
            mock.CreateConfig(project, config);
        } catch (LogException e) {
            assertEquals("code", e.GetErrorCode());
            assertEquals("message", e.GetErrorMessage());
        }
    }

    @Test
    public void TestUpdateConfig() {
        ResponseMessage response = new ResponseMessage();

        Map<String, String> resHeaders = new HashMap<String, String>();
        resHeaders.put(Consts.CONST_X_SLS_REQUESTID, "TESTREQID");
        response.setHeaders(resHeaders);
        response.setStatusCode(200);

        String testConfigName = "test_config";

        Config config = new Config(testConfigName);
        JSONObject inputDetail = new JSONObject();

        inputDetail = new JSONObject();
        inputDetail.put("logType", "apsara_log");
        inputDetail.put("logPath", "/var/log/httpd1/");
        inputDetail.put("filePattern", "access1.log");
        inputDetail.put("localStorage", false);
        inputDetail.put("timeFormat", "%h");
        inputDetail.put("logBeginRegex", "\\w+");
        inputDetail.put("regex", "(\\w+) (\\w+)");
        inputDetail.put("topicFormat", "testlog");

        JSONArray key = new JSONArray();
        key.add("name3");
        key.add("seqno3");
        inputDetail.put("key", key);

        JSONArray filterKey = new JSONArray();
        inputDetail.put("filterKey", filterKey);

        JSONArray filterRegex = new JSONArray();
        inputDetail.put("filterRegex", filterRegex);

        try {
            config.SetInputDetail(inputDetail.toString());
        } catch (LogException e) {
            e.printStackTrace();
        }

        JSONObject outputDetail = new JSONObject();
        outputDetail.put("projectName", "ay421");
        outputDetail.put("logstoreName", "perfcounter1");

        String project = "test-project";

        try {
            config.SetOutputDetail(outputDetail.toString());
        } catch (LogException e) {
            fail(e.getMessage());
        }

        try {
            mock.ChangeResponse(response);
            mock.UpdateConfig(project, config);
        } catch (LogException e) {
            fail(e.getMessage());
        }

        byte[] errorBody = null;
        try {
            errorBody = SlsClientTestData.TEST_STANDARD_ERROR.getBytes("utf-8");
        } catch (UnsupportedEncodingException e) {
            fail(e.getMessage());
        }
        InputStream errorContent = new ByteArrayInputStream(errorBody);
        response.setStatusCode(400);
        response.setContent(errorContent);
        mock.ChangeResponse(response);
        try {
            mock.UpdateConfig(project, config);
        } catch (LogException e) {
            assertEquals("code", e.GetErrorCode());
            assertEquals("message", e.GetErrorMessage());
        }
    }

    @Test
    public void TestDeleteConfig() {
        ResponseMessage response = new ResponseMessage();

        Map<String, String> resHeaders = new HashMap<String, String>();
        resHeaders.put(Consts.CONST_X_SLS_REQUESTID, "TESTREQID");
        response.setHeaders(resHeaders);
        response.setStatusCode(200);

        String testConfigName = "test_config";
        String project = "test-project";

        try {
            mock.ChangeResponse(response);
            mock.DeleteConfig(project, testConfigName);
        } catch (LogException e) {
            fail(e.getMessage());
        }

        byte[] errorBody = null;
        try {
            errorBody = SlsClientTestData.TEST_STANDARD_ERROR.getBytes("utf-8");
        } catch (UnsupportedEncodingException e) {
            fail(e.getMessage());
        }
        InputStream errorContent = new ByteArrayInputStream(errorBody);
        response.setStatusCode(400);
        response.setContent(errorContent);
        mock.ChangeResponse(response);
        try {
            mock.DeleteConfig(project, testConfigName);
        } catch (LogException e) {
            assertEquals("code", e.GetErrorCode());
            assertEquals("message", e.GetErrorMessage());
        }
    }

    @Test
    public void TestGetConfig() {
        String testConfigName = "test_config";
        Config config = new Config(testConfigName);
        ConfigInputDetail inputDetail = new ConfigInputDetail();
        inputDetail.SetLogType("common_reg_log");
        inputDetail.SetLogPath("/var/log/httpd/");
        inputDetail.SetFilePattern("access.log");
        inputDetail.SetLocalStorage(true);
        inputDetail.SetTimeFormat("%H%m%S");
        inputDetail.SetLogBeginRegex("\\d+");
        inputDetail.SetRegex("(\\d+) (\\d+)");
        inputDetail.SetTopicFormat("none");

        ArrayList<String> key = new ArrayList<String>();
        key.add("number");
        key.add("seqno");
        inputDetail.SetKey(key);

        ArrayList<String> filterKey = new ArrayList<String>();
        filterKey.add("number1");
        filterKey.add("seqno1");


        ArrayList<String> filterRegex = new ArrayList<String>();
        filterRegex.add("number2");
        filterRegex.add("seqno2");
        inputDetail.SetFilterKeyRegex(filterKey, filterRegex);

        config.SetInputDetail(inputDetail);

        ConfigOutputDetail outputDetail = new ConfigOutputDetail("ay42","perfcounter","lz4");
        config.SetOutputDetail(outputDetail);

        JSONObject configDict = new JSONObject();
        configDict.put("configName", config.GetConfigName());
        configDict.put("inputDetail", ((ConfigInputDetail) (config.GetInputDetail())).ToJsonString());
        configDict.put("outputDetail", config.GetOutputDetail().ToJsonString());

        String jsonStr = configDict.toString();
        byte[] body = null;
        try {
            body = jsonStr.getBytes("utf-8");
        } catch (UnsupportedEncodingException e) {
            fail(e.getMessage());
        }
        InputStream content = new ByteArrayInputStream(body);

        ResponseMessage response = new ResponseMessage();

        Map<String, String> resHeaders = new HashMap<String, String>();
        resHeaders.put(Consts.CONST_X_SLS_REQUESTID, "TESTREQID");
        response.setHeaders(resHeaders);
        response.setStatusCode(200);
        response.setContent(content);
        response.SetBody(body);
        String project = "test-project";

        try {
            mock.ChangeResponse(response);
            GetConfigResponse res = mock.GetConfig(project, testConfigName);
            assertEquals("configName does not match", testConfigName, res.GetConfig().GetConfigName());

            assertEquals("logType does not match", inputDetail.GetLogType(), ((ConfigInputDetail) (((ConfigInputDetail) (res.GetConfig().GetInputDetail())))).GetLogType());
            assertEquals("logPath does not match", inputDetail.GetLogPath(), ((ConfigInputDetail) (res.GetConfig().GetInputDetail())).GetLogPath());
            assertEquals("filePattern does not match", inputDetail.GetFilePattern(), ((ConfigInputDetail) (res.GetConfig().GetInputDetail())).GetFilePattern());
            assertEquals("localStorage does not match", inputDetail.GetLocalStorage(), ((ConfigInputDetail) (res.GetConfig().GetInputDetail())).GetLocalStorage());
            assertEquals("timeFormat does not match", inputDetail.GetTimeFormat(), ((ConfigInputDetail) (res.GetConfig().GetInputDetail())).GetTimeFormat());
            assertEquals("logBeginRegex does not match", inputDetail.GetLogBeginRegex(), ((ConfigInputDetail) (res.GetConfig().GetInputDetail())).GetLogBeginRegex());
            assertEquals("regex does not match", inputDetail.GetRegex(), ((ConfigInputDetail) (res.GetConfig().GetInputDetail())).GetRegex());
            assertEquals("topicFormat does not match", inputDetail.GetTopicFormat(), ((ConfigInputDetail) (res.GetConfig().GetInputDetail())).GetTopicFormat());
        } catch (LogException e) {
            fail(e.getMessage());
        }

        byte[] errorBody = null;
        try {
            errorBody = SlsClientTestData.TEST_STANDARD_ERROR.getBytes("utf-8");
        } catch (UnsupportedEncodingException e) {
            fail(e.getMessage());
        }
        InputStream errorContent = new ByteArrayInputStream(errorBody);
        response.setStatusCode(400);
        response.setContent(errorContent);
        mock.ChangeResponse(response);
        try {
            mock.GetConfig(project, testConfigName);
        } catch (LogException e) {
            assertEquals("code", e.GetErrorCode());
            assertEquals("message", e.GetErrorMessage());
        }

        byte[] invalidBody = null;
        try {
            invalidBody = SlsClientTestData.TEST_INVALID_JSON.getBytes("utf-8");
        } catch (UnsupportedEncodingException e) {
            fail(e.getMessage());
        }
        InputStream invalidContent = new ByteArrayInputStream(invalidBody);
        response.setStatusCode(200);
        response.setContent(invalidContent);
        mock.ChangeResponse(response);
        try {
            mock.GetConfig(project, testConfigName);
        } catch (LogException e) {
            assertEquals("FailToGenerateConfig", e.GetErrorCode());
        }
    }

    @Test
    public void TestListConfig() {
        String testConfigName1 = "test_config1";
        String testConfigName2 = "test_config2";

        JSONArray testConfigs = new JSONArray();
        testConfigs.add(testConfigName1);
        testConfigs.add(testConfigName2);

        JSONObject obj = new JSONObject();
        obj.put("total", 4);
        obj.put("count", 2);
        obj.put("configs", testConfigs);

        String jsonStr = obj.toString();
        byte[] body = null;
        try {
            body = jsonStr.getBytes("utf-8");
        } catch (UnsupportedEncodingException e) {
            fail(e.getMessage());
        }
        InputStream content = new ByteArrayInputStream(body);

        ResponseMessage response = new ResponseMessage();

        Map<String, String> resHeaders = new HashMap<String, String>();
        resHeaders.put(Consts.CONST_X_SLS_REQUESTID, "TESTREQID");
        response.setHeaders(resHeaders);
        response.setStatusCode(200);
        response.setContent(content);
        response.SetBody(body);
        String project = "test-proeject";

        try {
            mock.ChangeResponse(response);
            mock.ListConfig(project, 0, 1);

            content = new ByteArrayInputStream(body);
            response.setContent(content);
            mock.ChangeResponse(response);
            mock.ListConfig(project, testConfigName1, 0, 1);

            content = new ByteArrayInputStream(body);
            response.setContent(content);
            mock.ChangeResponse(response);
            ListConfigResponse listRes = mock.ListConfig(project);
            assertEquals("total does not match", 4, listRes.GetTotal());
            assertEquals("size does not match", 2, listRes.GetCount());

            assertEquals("configNum does not match", testConfigs.size(), listRes.GetConfigs().size());
            for (int i = 0; i < testConfigs.size(); i++) {
                assertEquals("config " + i + " does not match", testConfigs.getString(i), listRes.GetConfigs().get(i));
            }
        } catch (LogException e) {
            assertTrue(e.getMessage(), false);
        }

        byte[] errorBody = null;
        try {
            errorBody = SlsClientTestData.TEST_STANDARD_ERROR.getBytes("utf-8");
        } catch (UnsupportedEncodingException e) {
            assertTrue(e.getMessage(), false);
        }
        InputStream errorContent = new ByteArrayInputStream(errorBody);
        response.setStatusCode(400);
        response.setContent(errorContent);
        mock.ChangeResponse(response);
        try {
            mock.ListConfig(project, testConfigName1, 0, 1);
        } catch (LogException e) {
            assertEquals("code", e.GetErrorCode());
            assertEquals("message", e.GetErrorMessage());
        }

        byte[] invalidBody = null;
        try {
            invalidBody = SlsClientTestData.TEST_INVALID_JSON.getBytes("utf-8");
        } catch (UnsupportedEncodingException e) {
            assertTrue(e.getMessage(), false);
        }
        InputStream invalidContent = new ByteArrayInputStream(invalidBody);
        response.setStatusCode(200);
        response.setContent(invalidContent);
        mock.ChangeResponse(response);
        try {
            mock.ListConfig(project, testConfigName1, 0, 1);
        } catch (LogException e) {
            assertEquals("BadResponse", e.GetErrorCode());
        }

        try {
            invalidBody = "{\"total\":\"4\",\"size\":\"2\",\"key\":\"invalid json\"}".getBytes("utf-8");
        } catch (UnsupportedEncodingException e) {
            assertTrue(e.getMessage(), false);
        }
        invalidContent = new ByteArrayInputStream(invalidBody);
        response.setStatusCode(200);
        response.setContent(invalidContent);
        mock.ChangeResponse(response);
        try {
            mock.ListConfig(project, testConfigName1, 0, 1);
        } catch (LogException e) {
            assertEquals("BadResponse", e.GetErrorCode());
        }
    }

    @Test
    public void TestCreateMachineGroup() {
        ResponseMessage response = new ResponseMessage();

        Map<String, String> resHeaders = new HashMap<String, String>();
        resHeaders.put(Consts.CONST_X_SLS_REQUESTID, "TESTREQID");
        response.setHeaders(resHeaders);
        response.setStatusCode(200);

        String testGroupName = "test_group";
        String machineIdentifyType = "uuid";
        String groupType = "";
        String externalName = "testgroup";

        ArrayList<String> machineList = new ArrayList<String>();
        machineList.add("UUID1");
        machineList.add("UUID2");

        MachineGroup group = new MachineGroup(testGroupName, "userdefined", machineList);
        group.SetMachineIdentifyType(machineIdentifyType);
        group.SetGroupType(groupType);
        group.SetExternalName(externalName);

        String project = "test-project";

        try {
            mock.ChangeResponse(response);
            mock.CreateMachineGroup(project, group);
        } catch (LogException e) {
            assertTrue(e.getMessage(), false);
        }

        byte[] errorBody = null;
        try {
