/******************************************************************************* * Copyright (c) 2007, 2011 Association for Decentralized Information Management in * Industry THTH ry. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * VTT Technical Research Centre of Finland - initial API and implementation *******************************************************************************/ package org.simantics.history.test; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.IOException; import org.junit.After; import org.junit.Assert; import org.junit.Before; import org.junit.Test; import org.simantics.databoard.Bindings; import org.simantics.databoard.Datatypes; import org.simantics.databoard.accessor.StreamAccessor; import org.simantics.databoard.accessor.error.AccessorException; import org.simantics.databoard.binding.Binding; import org.simantics.databoard.binding.impl.DoubleArrayBinding; import org.simantics.databoard.type.ArrayType; import org.simantics.databoard.type.RecordType; import org.simantics.databoard.util.Bean; import org.simantics.databoard.util.Limit; import org.simantics.databoard.util.Range; import org.simantics.history.Collector; import org.simantics.history.History; import org.simantics.history.HistoryException; import org.simantics.history.HistoryManager; import org.simantics.history.csv.CSVFormatter; import org.simantics.history.impl.CollectorImpl; import org.simantics.history.impl.CollectorState; import org.simantics.history.util.ProgressMonitor; import org.simantics.history.util.StreamIterator; import org.simantics.history.util.Stream; import org.simantics.history.util.ValueBand; import org.simantics.history.util.subscription.SubscriptionItem; import org.simantics.history.util.subscription.SamplingFormat; import org.simantics.utils.FileUtils; public class TestHistory { static final double NaN = Double.NaN; // Time 0.0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1.0 1.1 1.2 1.3 1.4 double[] data1 = { 5.0, 5.0, 5.0, 5.0, 6.0, 6.0, 6.0, 7.0, 8.0, 9.0, NaN,10.0, NaN, NaN, NaN }; double[] data2 = { 5.0, 5.0, 5.0, 5.0, 6.0, 6.0, 6.0, 7.0, 8.0, 9.0,10.0, 9.0, 5.0, 4.0, 3.0 }; byte[] data3 = { 5, 6, 7, 8, 9, 10, 9, 5, 4, 3 }; // Subscription formats SamplingFormat simple, allfields, vector, minmax, byteformat, string; // History HistoryManager historian; File workarea; Collector collector; @Before public void initSubscriptionFormats() { simple = new SamplingFormat(); simple.formatId = "simple"; RecordType format; format = (RecordType) (simple.format = new RecordType()); format.addComponent("time", Datatypes.FLOAT); format.addComponent("endTime", Datatypes.FLOAT); format.addComponent("value", Datatypes.DOUBLE ); format.addComponent("quality", Datatypes.BYTE ); simple.interval = NaN; simple.deadband = NaN; string = new SamplingFormat(); string.formatId = "string"; format = (RecordType) (string.format = new RecordType()); format.addComponent("time", Datatypes.FLOAT); format.addComponent("endTime", Datatypes.FLOAT); format.addComponent("value", Datatypes.STRING ); format.addComponent("quality", Datatypes.BYTE ); string.interval = NaN; string.deadband = NaN; allfields = new SamplingFormat(); allfields.formatId = "alldata"; format = (RecordType) (allfields.format = new RecordType()); format.addComponent("time", Datatypes.DOUBLE); format.addComponent("endTime", Datatypes.DOUBLE); format.addComponent("value", Datatypes.DOUBLE ); format.addComponent("lastValue", Datatypes.DOUBLE); format.addComponent("min", Datatypes.DOUBLE); format.addComponent("max", Datatypes.DOUBLE); format.addComponent("avg", Datatypes.DOUBLE); format.addComponent("median", Datatypes.DOUBLE); format.addComponent("quality", Datatypes.BYTE ); format.addComponent("count", Datatypes.INTEGER); allfields.interval = NaN; allfields.deadband = NaN; byteformat = new SamplingFormat(); byteformat.formatId = "byte"; byteformat.format = new RecordType(); format = (RecordType) (byteformat.format = new RecordType()); format.addComponent("time", Datatypes.DOUBLE); format.addComponent("endTime", Datatypes.DOUBLE); format.addComponent("value", Datatypes.BYTE); format.addComponent("lastValue", Datatypes.BYTE); format.addComponent("min", Datatypes.BYTE); format.addComponent("max", Datatypes.BYTE); format.addComponent("avg", Datatypes.DOUBLE); format.addComponent("median", Datatypes.BYTE); format.addComponent("quality", Datatypes.BYTE); format.addComponent("count", Datatypes.INTEGER); byteformat.interval = NaN; byteformat.deadband = NaN; vector = new SamplingFormat(); vector.formatId = "vector"; vector.format = new RecordType(); format = (RecordType) (vector.format = new RecordType()); format.addComponent("time", Datatypes.FLOAT); format.addComponent("endTime", Datatypes.FLOAT); format.addComponent("value", new ArrayType( Datatypes.DOUBLE, Range.between(Limit.inclusive(3), Limit.inclusive(3)) )); format.addComponent("count", Datatypes.INTEGER); vector.interval = NaN; vector.deadband = NaN; minmax = new SamplingFormat(); minmax.formatId = "minmax"; minmax.format = new RecordType(); format = (RecordType) (minmax.format = new RecordType()); format.addComponent("time", Datatypes.FLOAT); format.addComponent("endTime", Datatypes.FLOAT); format.addComponent("value", Datatypes.DOUBLE ); format.addComponent("min", Datatypes.DOUBLE ); format.addComponent("max", Datatypes.DOUBLE ); minmax.interval = Double.MAX_VALUE; minmax.deadband = Double.MAX_VALUE; } @Before public void initHistory() { CollectorState cs = new CollectorState(); workarea = FileUtils.createTmpDir(); System.out.println(workarea); historian = History.openFileHistory( workarea ); // historian = History.createMemoryHistory(); collector = new CollectorImpl( historian ); } @After public void uninitHistory() { if ( collector != null ) { collector.close(); } if ( historian != null ) { historian.close(); } if ( workarea != null) { try { FileUtils.deleteAll(workarea); } catch (IOException e) { e.printStackTrace(); } } } @Test public void testGetModifySubscription() throws Exception { // 1. Create Item and Collector SubscriptionItem hi = SubscriptionItem.createItem("NotMyVariable", "MySubscription", allfields); historian.create(hi); collector.addItem(hi); // 2. Get Item SubscriptionItem[] items = collector.getItems(); Assert.assertEquals(1, items.length); SubscriptionItem hii = new SubscriptionItem(); hii.readAvailableFields( items[0] ); Assert.assertTrue( hii.equalContents( hi ) ); // 3. Modify Item hi.variableId = "MyVariable"; collector.setItem(hi); items = collector.getItems(); Assert.assertEquals(1, items.length); hii.readAvailableFields( items[0] ); Assert.assertTrue( hii.equalContents( hi ) ); // 4. Remove & Add collector.removeItem(hi.id); Assert.assertEquals(0, collector.getItems().length); collector.addItem(hi); // 5. Open & Modify subscription collector.beginStep(Bindings.DOUBLE, 5.0); hi.interval = 1.2; collector.setItem(hi); collector.endStep(); collector.close(); // 6. Read from history Bean bean = historian.getItem(hi.id); hi.interval = 0.0; hi.readAvailableFields(bean); Assert.assertEquals(1.2, hi.interval, 0.1); } @Test public void failtestRecreateSubscription() throws HistoryException { Collector collector2; SubscriptionItem hi = SubscriptionItem.createItem("MyVariable", "MySubscription", allfields); historian.create(hi); collector.addItem( hi ); collector2 = new CollectorImpl( historian ); collector2.addItem( hi ); try { collector.beginStep(Bindings.DOUBLE, 0.0); collector2.beginStep(Bindings.DOUBLE, 0.0); Assert.fail("Recreate subscription should have failed"); } catch (HistoryException e) { // expected exception } collector2.close(); } @Test public void failtestReopenStream() throws HistoryException { // 1. Create history and collector item SamplingFormat format = allfields.clone(); format.deadband = 2.5; SubscriptionItem[] his = SubscriptionItem.createItems("MyVariable", "MySubscription", allfields, minmax); historian.create(his); StreamAccessor sa1=null, sa2=null; try { sa1 = historian.openStream(his[0].id, "r"); sa2 = historian.openStream(his[1].id, "r"); Assert.fail("HistoryManager must not allow to open two handles to same subscription"); } catch (HistoryException he) { // Expected exception } try { if (sa1!=null)sa1.close(); if (sa2!=null) sa2.close(); } catch (AccessorException e) { throw new HistoryException(e); } historian.delete( his[0].id, his[1].id ); } @Test public void testDisableItem() throws Exception { // 1. Create history and collector item SamplingFormat format = allfields.clone(); format.deadband = 2.5; SubscriptionItem[] hi = SubscriptionItem.createItems("MyVariable", "MySubscription", allfields, minmax); historian.create(hi); // 2. Create collector collector.addItems(hi); // Write data try { // Simulate double[] data = data1; for (int i=0; i<4; i++) { collector.beginStep(Bindings.DOUBLE, i * 0.1); collector.setValue("MyVariable", Bindings.DOUBLE, data[i]); collector.endStep(); } // Disable item hi[0].enabled = false; collector.setItem(hi[0]); for (int i=4; i<12; i++) { collector.beginStep(Bindings.DOUBLE, i * 0.1); collector.setValue("MyVariable", Bindings.DOUBLE, data[i]); collector.endStep(); } // Enable item hi[0].enabled = true; collector.setItem(hi[0]); for (int i=12; i