package org.epics.archiverappliance.retrieval.extrafields; import static org.junit.Assert.assertTrue; import java.io.IOException; import java.net.URLEncoder; import java.sql.Timestamp; import java.util.HashMap; import org.apache.log4j.Logger; import org.epics.archiverappliance.SIOCSetup; import org.epics.archiverappliance.TomcatSetup; import org.epics.archiverappliance.common.TimeUtils; import org.epics.archiverappliance.config.ConfigServiceForTests; import org.epics.archiverappliance.retrieval.client.EpicsMessage; import org.epics.archiverappliance.retrieval.client.GenMsgIterator; import org.epics.archiverappliance.retrieval.client.InfoChangeHandler; import org.epics.archiverappliance.retrieval.client.RawDataRetrieval; import org.epics.archiverappliance.utils.ui.GetUrlContent; import org.json.simple.JSONObject; import org.junit.After; import org.junit.Before; import org.junit.Test; import org.openqa.selenium.By; import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebElement; import org.openqa.selenium.firefox.FirefoxDriver; import edu.stanford.slac.archiverappliance.PB.EPICSEvent.PayloadInfo; /** * We want to make sure we capture changes in EGU and return them as part of the retrieval request. * We archive a PV, then get data (and thus the EGU). * We then caput the EGU and then fetch the data again... * @author mshankar * */ public class EGUChangeTest { private static Logger logger = Logger.getLogger(EGUChangeTest.class.getName()); TomcatSetup tomcatSetup = new TomcatSetup(); SIOCSetup siocSetup = new SIOCSetup(); WebDriver driver; private String pvName = "UnitTestNoNamingConvention:sine"; @Before public void setUp() throws Exception { siocSetup.startSIOCWithDefaultDB(); tomcatSetup.setUpWebApps(this.getClass().getSimpleName()); driver = new FirefoxDriver(); } @After public void tearDown() throws Exception { driver.quit(); tomcatSetup.tearDown(); siocSetup.stopSIOC(); } @Test public void testSimpleArchivePV() throws Exception { driver.get("http://localhost:17665/mgmt/ui/index.html"); WebElement pvstextarea = driver.findElement(By.id("archstatpVNames")); pvstextarea.sendKeys(pvName); WebElement archiveButton = driver.findElement(By.id("archstatArchive")); logger.debug("About to submit"); archiveButton.click(); // We have to wait for a few minutes here here as it does take a while for the workflow to complete. Thread.sleep(5*60*1000); WebElement checkStatusButton = driver.findElement(By.id("archstatCheckStatus")); checkStatusButton.click(); Thread.sleep(2*1000); WebElement statusPVName = driver.findElement(By.cssSelector("#archstatsdiv_table tr:nth-child(1) td:nth-child(1)")); String pvNameObtainedFromTable = statusPVName.getText(); assertTrue("PV Name is not " + pvName + "; instead we get " + pvNameObtainedFromTable, pvName.equals(pvNameObtainedFromTable)); WebElement statusPVStatus = driver.findElement(By.cssSelector("#archstatsdiv_table tr:nth-child(1) td:nth-child(2)")); String pvArchiveStatusObtainedFromTable = statusPVStatus.getText(); String expectedPVStatus = "Being archived"; assertTrue("Expecting PV archive status to be " + expectedPVStatus + "; instead it is " + pvArchiveStatusObtainedFromTable, expectedPVStatus.equals(pvArchiveStatusObtainedFromTable)); Thread.sleep(1*60*1000); // We have now archived this PV, get some data and make sure the EGU is as expected. checkEGU("apples"); SIOCSetup.caput(pvName + ".EGU", "oranges"); Thread.sleep(5*1000); // Pause and resume the PV to reget the meta data String pausePVURL = "http://localhost:17665/mgmt/bpl/pauseArchivingPV?pv=" + URLEncoder.encode(pvName, "UTF-8"); JSONObject pauseStatus = GetUrlContent.getURLContentAsJSONObject(pausePVURL); assertTrue("Cannot pause PV", pauseStatus.containsKey("status") && pauseStatus.get("status").equals("ok")); logger.info("Done pausing PV " + pvName); Thread.sleep(5*1000); String resumePVURL = "http://localhost:17665/mgmt/bpl/resumeArchivingPV?pv=" + URLEncoder.encode(pvName, "UTF-8"); JSONObject resumeStatus = GetUrlContent.getURLContentAsJSONObject(resumePVURL); assertTrue("Cannot resume PV", resumeStatus.containsKey("status") && resumeStatus.get("status").equals("ok")); logger.info("Done resuming PV " + pvName); // Now check the EGU again... Thread.sleep(1*60*1000); checkEGU("oranges"); } private void checkEGU(String expectedEGUValue) throws IOException { RawDataRetrieval rawDataRetrieval = new RawDataRetrieval("http://localhost:" + ConfigServiceForTests.RETRIEVAL_TEST_PORT+ "/retrieval/data/getData.raw"); Timestamp now = TimeUtils.now(); Timestamp start = TimeUtils.minusDays(now, 100); Timestamp end = TimeUtils.plusDays(now, 10); int eventCount = 0; final HashMap<String, String> metaFields = new HashMap<String, String>(); // Make sure we get the EGU as part of a regular VAL call. try(GenMsgIterator strm = rawDataRetrieval.getDataForPV(pvName, start, end, false, null)) { PayloadInfo info = null; assertTrue("We should get some data, we are getting a null stream back", strm != null); info = strm.getPayLoadInfo(); assertTrue("Stream has no payload info", info != null); mergeHeaders(info, metaFields); strm.onInfoChange(new InfoChangeHandler() { @Override public void handleInfoChange(PayloadInfo info) { mergeHeaders(info, metaFields); } }); for(@SuppressWarnings("unused") EpicsMessage dbrevent : strm) { eventCount++; } } assertTrue("We should have gotten some data back in retrieval. We got " + eventCount, eventCount > 0); assertTrue("The final value of EGU is " + metaFields.get("EGU") + ". We expected " + expectedEGUValue, expectedEGUValue.equals(metaFields.get("EGU"))); } private static void mergeHeaders(PayloadInfo info, HashMap<String, String> headers) { int headerCount = info.getHeadersCount(); for(int i = 0; i < headerCount; i++) { String headerName = info.getHeaders(i).getName(); String headerValue = info.getHeaders(i).getVal(); logger.info("Adding header " + headerName + " = " + headerValue); headers.put(headerName, headerValue); } } }