/** * personium.io * Copyright 2014 FUJITSU LIMITED * * Licensed 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 com.fujitsu.dc.test.unit.core.model.impl.es.repair; import static org.junit.Assert.assertEquals; import static org.junit.Assert.fail; import java.util.ArrayList; import java.util.List; import org.json.simple.JSONObject; import org.junit.After; import org.junit.Before; import org.junit.Ignore; import org.junit.Test; import org.junit.experimental.categories.Category; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.fujitsu.dc.common.ads.AdsWriteFailureLogException; import com.fujitsu.dc.common.ads.AdsWriteFailureLogInfo; import com.fujitsu.dc.common.es.EsType; import com.fujitsu.dc.common.es.response.DcIndexResponse; import com.fujitsu.dc.common.es.response.DcSearchResponse; import com.fujitsu.dc.common.es.util.DcUUID; import com.fujitsu.dc.core.DcCoreConfig; import com.fujitsu.dc.core.model.impl.es.EsModel; import com.fujitsu.dc.core.model.impl.es.ads.Ads; import com.fujitsu.dc.core.model.impl.es.ads.AdsConnectionException; import com.fujitsu.dc.core.model.impl.es.ads.AdsException; import com.fujitsu.dc.core.model.impl.es.ads.JdbcAds; import com.fujitsu.dc.core.model.impl.es.doc.EntitySetDocHandler; import com.fujitsu.dc.core.model.impl.es.doc.OEntityDocHandler; import com.fujitsu.dc.core.model.impl.es.repair.AdsAccessor; import com.fujitsu.dc.core.model.impl.es.repair.EsAccessor; import com.fujitsu.dc.core.model.impl.es.repair.RepairAds; import com.fujitsu.dc.core.model.impl.es.repair.RepairAdsException; import com.fujitsu.dc.test.categories.Unit; /** * RepairAdsTest ユニットテストクラス. */ @Category({Unit.class }) public class RepairAdsTest { private static final String ROUTING_ID = "routingId"; static Logger log = LoggerFactory.getLogger(RepairAdsTest.class); private String idxName = DcCoreConfig.getEsUnitPrefix() + "_anon"; private String id = "repair_" + DcUUID.randomUUID(); private String[] idList = {id }; private Ads ads; /** * すべてのテスト毎に1度実行される処理. * @throws InterruptedException InterruptedException * @throws AdsConnectionException AdsConnectionException */ @Before @SuppressWarnings("unchecked") public void before() throws InterruptedException, AdsConnectionException { ads = new JdbcAds(); // Typeの定義 // (Type 名に # は使えないっぽい。) EsType type = EsModel.type(idxName, "UserData", ROUTING_ID, 0, 0); // ドキュメント登録 JSONObject json1 = new JSONObject(); json1.put("c", ROUTING_ID); json1.put("p", Long.parseLong("1406595596944")); json1.put("u", Long.parseLong("1406595596944")); DcIndexResponse res1 = type.create(id, json1); assertEquals(idList[0], res1.getId()); } /** * すべてのテスト毎に1度実行される処理. * @throws InterruptedException InterruptedException */ @After public void after() throws InterruptedException { // 作成したインデックスを消す EsType type = EsModel.type(idxName, "UserData", ROUTING_ID, 0, 0); type.delete(id); } /** * Journalログのディレクトリが不正の場合_DcRepairAdsExceptionが発生すること. * @throws RepairAdsException DcRepairAdsException */ @Ignore @Test public void Journalログのディレクトリが不正の場合_DcRepairAdsExceptionが発生すること() throws RepairAdsException { // RepairAds repair = RepairAds.getInstance(); // repair.readProperties(); // repair.correctAdsWriteFailureLogFiles(); } /** * Journalログのローテートファイルが存在しない場合_DcRepairAdsExceptionが発生すること. */ @Ignore @Test public void Journalログのローテートファイルが存在しない場合_DcRepairAdsExceptionが発生すること() { } /** * Elasticsearchの検索結果が2件以上の場合_AdsExceptionが発生すること. * @throws RepairAdsException DcRepairAdsException * @throws AdsWriteFailureLogException AdsWriteFailureLogException * @throws AdsException AdsException */ @Ignore // ESへ同じUUIDを登録することが不可能のため。パワーモックを使用すると行けるかも。 @Test public void Elasticsearchの検索結果が2件以上の場合_AdsExceptionが発生すること() throws RepairAdsException, AdsWriteFailureLogException, AdsException { try { AdsAccessor.initializedAds(); RepairAds repair = RepairAds.getInstance(); StringBuilder sbuf = new StringBuilder(); sbuf.append(DcCoreConfig.getEsUnitPrefix() + "_anon\t"); sbuf.append("ComplexTypeProperty\t"); sbuf.append("odata-gsX3t2q3Qz6jdIn30fFMaQ\t"); sbuf.append("aCUuueHzTKCPchE0yxTZZA\t"); sbuf.append(id + "\t"); sbuf.append("CREATE\t"); sbuf.append("1\t"); sbuf.append("1408595358931"); AdsWriteFailureLogInfo logInfo = AdsWriteFailureLogInfo.parse(sbuf.toString()); List<String> list = new ArrayList<String>(); list.add("abc"); DcSearchResponse esResponse = EsAccessor.search(idxName, ROUTING_ID, list, "UserData"); List<JSONObject> adsResponse = AdsAccessor.getIdListOnAds(logInfo); repair.repairToAds(logInfo, esResponse, adsResponse); fail(); } catch (AdsException e) { System.out.println("OK"); } } /** * ADSの検索結果が2件以上の場合_AdsExceptionが発生すること. * @throws AdsWriteFailureLogException AdsWriteFailureLogException * @throws AdsException AdsException */ @Ignore // ADSへ同じUUIDを登録することが不可能のため。パワーモックを使用すると行けるかも。 @Test public void ADSの検索結果が2件以上の場合_AdsExceptionが発生すること() throws AdsWriteFailureLogException, AdsException { try { AdsAccessor.initializedAds(); RepairAds repair = RepairAds.getInstance(); // AdsWriteFailureLogInfoを生成 StringBuilder sbuf = new StringBuilder(); sbuf.append(DcCoreConfig.getEsUnitPrefix() + "_anon\t"); sbuf.append("ComplexTypeProperty\t"); sbuf.append("odata-gsX3t2q3Qz6jdIn30fFMaQ\t"); sbuf.append("aCUuueHzTKCPchE0yxTZZA\t"); sbuf.append(id + "\t"); sbuf.append("CREATE\t"); sbuf.append("1\t"); sbuf.append("1408595358931"); AdsWriteFailureLogInfo logInfo = AdsWriteFailureLogInfo.parse(sbuf.toString()); // 前準備で登録したデータをESから取得する List<String> list = new ArrayList<String>(); list.add(id); DcSearchResponse esResponse = EsAccessor.search(idxName, ROUTING_ID, list, "UserData"); // ADSへ同じデータを2件登録する AdsAccessor.createAds(idxName, "Cell", esResponse); // AdsAccessor.createAds(idxName, "Cell", esResponse); // ADSから対象データを検索する(2件ヒット) List<JSONObject> adsResponse = AdsAccessor.getIdListOnAds(logInfo); // DcRepairAdsExceptionが発生すること repair.repairToAds(logInfo, esResponse, adsResponse); fail(); } catch (RepairAdsException e) { System.out.println("OK"); } finally { // ADSのデータを削除 ads.deleteCell(idxName, id); // ads.deleteCell(idxName, id); } } /** * リペア対象のデータがESに存在し、ADSに存在しない場合にADSに登録処理がされること. * @throws AdsWriteFailureLogException AdsWriteFailureLogException * @throws RepairAdsException DcRepairAdsException * @throws AdsException AdsException */ @Test public void リペア対象のデータがESに存在_ADSに存在しない場合にADSに登録処理がされること() throws AdsWriteFailureLogException, RepairAdsException, AdsException { try { AdsAccessor.initializedAds(); RepairAds repair = RepairAds.getInstance(); // AdsWriteFailureLogInfoを生成 StringBuilder sbuf = new StringBuilder(); sbuf.append(DcCoreConfig.getEsUnitPrefix() + "_anon\t"); sbuf.append("ComplexTypeProperty\t"); sbuf.append("odata-gsX3t2q3Qz6jdIn30fFMaQ\t"); sbuf.append("aCUuueHzTKCPchE0yxTZZA\t"); sbuf.append(id + "\t"); sbuf.append("CREATE\t"); sbuf.append("1\t"); sbuf.append("1408595358931"); AdsWriteFailureLogInfo logInfo = AdsWriteFailureLogInfo.parse(sbuf.toString()); // 前準備で登録したデータをESから取得する List<String> list = new ArrayList<String>(); list.add(id); DcSearchResponse esResponse = EsAccessor.search(idxName, ROUTING_ID, list, "UserData"); // ADSから対象データを検索する List<JSONObject> adsResponseBefore = AdsAccessor.getIdListOnAds(logInfo); // ADSにデータが登録されること repair.repairToAds(logInfo, esResponse, adsResponseBefore); // ADSから対象データを検索する List<JSONObject> adsResponseAfter = AdsAccessor.getIdListOnAds(logInfo); // ADSのデータが1件であること assertEquals(1, adsResponseAfter.size()); } finally { ads.deleteEntity(idxName, id); } } /** * リペア対象のデータがESとADSに存在し、ジャーナルログのデータバージョンとESのデータバージョンが同じ場合_更新処理がされること. * @throws AdsWriteFailureLogException AdsWriteFailureLogException * @throws RepairAdsException DcRepairAdsException * @throws AdsException AdsException */ @SuppressWarnings("unchecked") @Test public void リペア対象のデータがESとADSに存在かつジャーナルログのデータバージョンとESのデータバージョンが同じ場合_更新処理がされること() throws AdsWriteFailureLogException, RepairAdsException, AdsException { try { AdsAccessor.initializedAds(); RepairAds repair = RepairAds.getInstance(); // ADSにデータを登録する List<String> list = new ArrayList<String>(); list.add(id); DcSearchResponse esResponse = EsAccessor.search(idxName, ROUTING_ID, list, "UserData"); AdsAccessor.createAds(idxName, "Entity", esResponse); // ESにデータ更新をする(バージョンが2) EsType type = EsModel.type(idxName, "UserData", ROUTING_ID, 0, 0); // ドキュメント登録 JSONObject json1 = new JSONObject(); json1.put("c", ROUTING_ID); json1.put("p", Long.parseLong("1406595596955")); json1.put("u", Long.parseLong("1406595596955")); type.update(id, json1); // AdsWriteFailureLogInfoを生成 StringBuilder sbuf = new StringBuilder(); sbuf.append(DcCoreConfig.getEsUnitPrefix() + "_anon\t"); sbuf.append("ComplexTypeProperty\t"); sbuf.append("odata-gsX3t2q3Qz6jdIn30fFMaQ\t"); sbuf.append("aCUuueHzTKCPchE0yxTZZA\t"); sbuf.append(id + "\t"); sbuf.append("UPDATE\t"); sbuf.append("2\t"); sbuf.append("1408595358931"); AdsWriteFailureLogInfo logInfo = AdsWriteFailureLogInfo.parse(sbuf.toString()); // 前準備で登録したデータをESから取得する esResponse = EsAccessor.search(idxName, ROUTING_ID, list, "UserData"); // ADSから対象データを検索する(ヒット) List<JSONObject> adsResponseBefore = AdsAccessor.getIdListOnAds(logInfo); // ADSのデータが更新されること repair.repairToAds(logInfo, esResponse, adsResponseBefore); // ADSから対象データを検索する List<JSONObject> adsResponseAfter = AdsAccessor.getIdListOnAds(logInfo); // チェック // 登録前と登録後のデータ取得件数が等しい assertEquals(adsResponseBefore.size(), adsResponseAfter.size()); // データ更新日時が更新前と異なること JSONObject jsonBefore = (JSONObject) adsResponseBefore.get(0).get("source"); JSONObject jsonAfter = (JSONObject) adsResponseAfter.get(0).get("source"); if (jsonBefore.get("u").equals(jsonAfter.get("u"))) { fail(); } } finally { ads.deleteEntity(idxName, id); } } /** * リペア対象のデータがADSに存在し、ESに存在しない場合にADSに削除処理がされること. * @throws AdsWriteFailureLogException AdsWriteFailureLogException * @throws RepairAdsException DcRepairAdsException * @throws AdsException AdsException */ @Test public void リペア対象のデータがADSに存在しESに存在しない場合にADSに削除処理がされること() throws AdsWriteFailureLogException, RepairAdsException, AdsException { AdsAccessor.initializedAds(); RepairAds repair = RepairAds.getInstance(); // AdsWriteFailureLogInfoを生成 StringBuilder sbuf = new StringBuilder(); sbuf.append(DcCoreConfig.getEsUnitPrefix() + "_anon\t"); sbuf.append("ComplexTypeProperty\t"); sbuf.append("odata-gsX3t2q3Qz6jdIn30fFMaQ\t"); sbuf.append("aCUuueHzTKCPchE0yxTZZA\t"); sbuf.append(id + "\t"); sbuf.append("CREATE\t"); sbuf.append("1\t"); sbuf.append("1408595358931"); AdsWriteFailureLogInfo logInfo = AdsWriteFailureLogInfo.parse(sbuf.toString()); // 前準備で登録したデータをESから取得する List<String> list = new ArrayList<String>(); list.add(id); DcSearchResponse esResponse = EsAccessor.search(idxName, ROUTING_ID, list, "UserData"); // ADSにデータを登録 EntitySetDocHandler oedh = new OEntityDocHandler(esResponse.getHits().getHits()[0]); ads.createEntity(idxName, oedh); // ESからデータを削除する EsType type = EsModel.type(idxName, "UserData", ROUTING_ID, 0, 0); type.delete(id); // ADSから対象データを検索する(ヒット) List<JSONObject> adsResponseBefore = AdsAccessor.getIdListOnAds(logInfo); // ESから対象データを検索する(0件) esResponse = EsAccessor.search(idxName, ROUTING_ID, list, "UserData"); // ADSにデータが削除されること repair.repairToAds(logInfo, esResponse, adsResponseBefore); // ADSから対象データを検索する List<JSONObject> adsResponseAfter = AdsAccessor.getIdListOnAds(logInfo); // ADSのデータが0件であること assertEquals(0, adsResponseAfter.size()); } /** * リペア対象のデータがADSとESに存在しない場合にリペア処理が無視されること. * @throws AdsWriteFailureLogException AdsWriteFailureLogException * @throws RepairAdsException DcRepairAdsException * @throws AdsException AdsException */ @Test public void リペア対象のデータがADSとESに存在しない場合にリペア処理が無視されること() throws AdsWriteFailureLogException, RepairAdsException, AdsException { AdsAccessor.initializedAds(); RepairAds repair = RepairAds.getInstance(); // AdsWriteFailureLogInfoを生成 StringBuilder sbuf = new StringBuilder(); sbuf.append(DcCoreConfig.getEsUnitPrefix() + "_anon\t"); sbuf.append("ComplexTypeProperty\t"); sbuf.append("odata-gsX3t2q3Qz6jdIn30fFMaQ\t"); sbuf.append("aCUuueHzTKCPchE0yxTZZA\t"); sbuf.append("dummy_repair\t"); sbuf.append("CREATE\t"); sbuf.append("1\t"); sbuf.append("1408595358931"); AdsWriteFailureLogInfo logInfo = AdsWriteFailureLogInfo.parse(sbuf.toString()); // 前準備で登録したデータをESから取得する List<String> list = new ArrayList<String>(); list.add("dummy_repair"); // ADSから対象データを検索する(0件) List<JSONObject> adsResponseBefore = AdsAccessor.getIdListOnAds(logInfo); // ESから対象データを検索する(0件) DcSearchResponse esResponse = EsAccessor.search(idxName, ROUTING_ID, list, "UserData"); // 対象データのリペア処理が無視されること repair.repairToAds(logInfo, esResponse, adsResponseBefore); // ADSから対象データを検索する List<JSONObject> adsResponseAfter = AdsAccessor.getIdListOnAds(logInfo); // ADSのデータが0件であること assertEquals(0, adsResponseAfter.size()); } /** * リペア対象のデータがESとADSに存在し、ジャーナルログのデータバージョンとESのデータバージョンが異なる場合_処理が無視されること. * @throws AdsWriteFailureLogException AdsWriteFailureLogException * @throws RepairAdsException DcRepairAdsException * @throws AdsException AdsException */ @SuppressWarnings("unchecked") @Test public void リペア対象のデータがESとADSに存在してジャーナルログのデータバージョンとESのデータバージョンが異なる場合_処理が無視されること() throws AdsWriteFailureLogException, RepairAdsException, AdsException { try { AdsAccessor.initializedAds(); RepairAds repair = RepairAds.getInstance(); // ADSにデータを登録する List<String> list = new ArrayList<String>(); list.add(id); DcSearchResponse esResponse = EsAccessor.search(idxName, ROUTING_ID, list, "UserData"); AdsAccessor.createAds(idxName, "Entity", esResponse); // ESにデータ更新をする(バージョンが2) EsType type = EsModel.type(idxName, "UserData", ROUTING_ID, 0, 0); // ドキュメント登録 JSONObject json1 = new JSONObject(); json1.put("c", ROUTING_ID); json1.put("p", Long.parseLong("1406595596955")); json1.put("u", Long.parseLong("1406595596955")); type.update(id, json1); // AdsWriteFailureLogInfoを生成 StringBuilder sbuf = new StringBuilder(); sbuf.append(DcCoreConfig.getEsUnitPrefix() + "_anon\t"); sbuf.append("ComplexTypeProperty\t"); sbuf.append("odata-gsX3t2q3Qz6jdIn30fFMaQ\t"); sbuf.append("aCUuueHzTKCPchE0yxTZZA\t"); sbuf.append(id + "\t"); sbuf.append("UPDATE\t"); sbuf.append("1\t"); sbuf.append("1408595358931"); AdsWriteFailureLogInfo logInfo = AdsWriteFailureLogInfo.parse(sbuf.toString()); // 前準備で登録したデータをESから取得する esResponse = EsAccessor.search(idxName, ROUTING_ID, list, "UserData"); // ADSから対象データを検索する(ヒット) List<JSONObject> adsResponseBefore = AdsAccessor.getIdListOnAds(logInfo); // ADSのデータが更新されること repair.repairToAds(logInfo, esResponse, adsResponseBefore); // ADSから対象データを検索する List<JSONObject> adsResponseAfter = AdsAccessor.getIdListOnAds(logInfo); // チェック // 登録前と登録後のデータ取得件数が等しい assertEquals(adsResponseBefore.size(), adsResponseAfter.size()); // データ更新日時が更新前と異なること JSONObject jsonBefore = (JSONObject) adsResponseBefore.get(0).get("source"); JSONObject jsonAfter = (JSONObject) adsResponseAfter.get(0).get("source"); assertEquals(jsonBefore.get("u"), jsonAfter.get("u")); } finally { ads.deleteEntity(idxName, id); } } }