package org.yamcs.archive; import static org.junit.Assert.*; import static org.yamcs.api.artemis.Protocol.DATA_TYPE_HEADER_NAME; import static org.yamcs.api.artemis.Protocol.decode; import java.util.ArrayList; import java.util.List; import java.util.concurrent.atomic.AtomicInteger; import org.apache.activemq.artemis.api.core.SimpleString; import org.apache.activemq.artemis.api.core.client.ClientMessage; import org.apache.activemq.artemis.api.core.client.MessageHandler; import org.apache.activemq.artemis.core.server.embedded.EmbeddedActiveMQ; import org.junit.AfterClass; import org.junit.BeforeClass; import org.junit.Test; import org.yamcs.tctm.ParameterDataLinkInitialiser; import org.yamcs.StreamInitializer; import org.yamcs.api.YamcsApiException; import org.yamcs.api.artemis.Protocol; import org.yamcs.api.artemis.YamcsClient; import org.yamcs.api.artemis.YamcsSession; import org.yamcs.api.artemis.YamcsClient.ClientBuilder; import org.yamcs.artemis.ArtemisServer; import org.yamcs.artemis.PpTupleTranslator; import org.yamcs.artemis.StreamAdapter; import org.yamcs.protobuf.Pvalue.ParameterData; import org.yamcs.protobuf.Pvalue.ParameterValue; import org.yamcs.protobuf.Pvalue.ParameterData.Builder; import org.yamcs.protobuf.Yamcs.NamedObjectId; import org.yamcs.protobuf.Yamcs.ProtoDataType; import org.yamcs.protobuf.Yamcs.Value; import org.yamcs.protobuf.Yamcs.Value.Type; import org.yamcs.utils.TimeEncoding; import org.yamcs.yarch.DataType; import org.yamcs.yarch.Stream; import org.yamcs.yarch.Tuple; import org.yamcs.yarch.TupleDefinition; import org.yamcs.yarch.YarchTestCase; public class PpTupleTranslatorTest extends YarchTestCase { static EmbeddedActiveMQ artemisServer; public static int sequenceCount = 0; public static final String COL_BYTE = "/pp/byte"; public static final String COL_STR = "/pp/string"; public static final String COL_DOUBLE = "/pp/double"; @BeforeClass public static void setUpBeforeClass() throws Exception { artemisServer = ArtemisServer.setupArtemis(); } @AfterClass public static void tearDownAfterClass() throws Exception { artemisServer.stop(); } /** * Gets a sample message containing three simulated processed parameters * and timestamped for now, with a continually incrementing sequence * number. * * @param ys * @return */ public static ClientMessage getMessage( YamcsSession ys ) { Builder b = ParameterData.newBuilder(); b.addParameter( ParameterValue.newBuilder().setEngValue( Value.newBuilder().setType( Type.SINT32 ).setSint32Value( 1 ).build() ).setId( NamedObjectId.newBuilder().setName( COL_BYTE ).build() ) ); b.addParameter( ParameterValue.newBuilder().setEngValue( Value.newBuilder().setType( Type.STRING ).setStringValue( "test" ).build() ).setId( NamedObjectId.newBuilder().setName( COL_STR ).build() ) ); b.addParameter( ParameterValue.newBuilder().setEngValue( Value.newBuilder().setType( Type.DOUBLE ).setDoubleValue( 1.234 ).build() ).setId( NamedObjectId.newBuilder().setName( COL_DOUBLE ).build() ) ); ClientMessage msg = ys.session.createMessage( false ); Protocol.encode( msg, b.build() ); msg.putIntProperty( DATA_TYPE_HEADER_NAME, ProtoDataType.PP.getNumber() ); long curTime = TimeEncoding.getWallclockTime(); msg.putLongProperty( ParameterDataLinkInitialiser.PARAMETER_TUPLE_COL_GENTIME, curTime - 10 ); msg.putStringProperty( ParameterDataLinkInitialiser.PARAMETER_TUPLE_COL_GROUP, "no-group" ); msg.putIntProperty( ParameterDataLinkInitialiser.PARAMETER_TUPLE_COL_SEQ_NUM, PpTupleTranslatorTest.sequenceCount ++ ); msg.putLongProperty( ParameterDataLinkInitialiser.PARAMETER_TUPLE_COL_RECTIME, curTime ); return msg; } public static Tuple getTuple() { TupleDefinition tupleDef = ParameterDataLinkInitialiser.PARAMETER_TUPLE_DEFINITION.copy(); tupleDef.addColumn( COL_BYTE, DataType.BYTE ); tupleDef.addColumn( COL_STR, DataType.STRING ); tupleDef.addColumn( COL_DOUBLE, DataType.DOUBLE ); List<Object> cols=new ArrayList<Object>(4); cols.add( TimeEncoding.getWallclockTime() - 10 ); cols.add( "no-group" ); cols.add( PpTupleTranslatorTest.sequenceCount ++ ); cols.add( TimeEncoding.getWallclockTime() ); cols.add( 1 ); // byte cols.add( "test" ); // string cols.add( 1.234 ); // float return new Tuple(tupleDef, cols); } @Test public void testTranslation() throws Exception { StreamInitializer streamInit = new StreamInitializer(ydb.getName()); streamInit.createStreams(); ParameterRecorder ppRecorder = new ParameterRecorder(ydb.getName()); ppRecorder.startAsync(); // Get the stream Stream rtstream = ydb.getStream( "pp_realtime" ); assertNotNull(rtstream); // Add the adapter under test SimpleString address = new SimpleString("pp_realtime"); StreamAdapter streamAdapter = new StreamAdapter(rtstream, address, new PpTupleTranslator() ); // Create a client to generate messages with YamcsSession ys = YamcsSession.newBuilder().build(); ClientBuilder cb = ys.newClientBuilder(); cb.setDataProducer( true ); // We produce data cb.setDataConsumer( address,null ); // This is the destination for the produced data YamcsClient msgClient = cb.build(); final AtomicInteger hornetReceivedCounter=new AtomicInteger(0); // msgClient.dataConsumer.setMessageHandler ( new MessageHandler() { @Override public void onMessage(ClientMessage msg) { try { ParameterData pd = (ParameterData)decode( msg, ParameterData.newBuilder() ); assertEquals( 3, pd.getParameterCount() ); // Count received messages hornetReceivedCounter.getAndIncrement(); } catch (YamcsApiException e) { fail("Exception received: "+e); } } } ); // Now send some messages final int numMessages = 100; for( int i=0; i<numMessages; i++ ) { msgClient.sendData( address, getMessage( ys ) ); } Thread.sleep( 3000 ); // And make sure the messages have appeared in the table execute("create stream stream_pp_out as select * from "+ParameterRecorder.TABLE_NAME); List<Tuple> tlist = fetchAllFromTable(ParameterRecorder.TABLE_NAME); assertEquals(numMessages, tlist.size()); for(int i=0; i<numMessages; i++) { Tuple tuple = tlist.get(i); org.yamcs.parameter.ParameterValue pv = (org.yamcs.parameter.ParameterValue)tuple.getColumn( COL_STR ); assertTrue( "test".equals( pv.getEngValue().getStringValue() ) ); pv = (org.yamcs.parameter.ParameterValue)tuple.getColumn( COL_DOUBLE ); assertEquals( 1.234, pv.getEngValue().getDoubleValue(), 0.0001 ); pv = (org.yamcs.parameter.ParameterValue)tuple.getColumn( COL_BYTE ); assertEquals( 1, pv.getEngValue().getSint32Value() ); assertTrue( "no-group".equals( tuple.getColumn( ParameterDataLinkInitialiser.PARAMETER_TUPLE_COL_GROUP ) ) ); assertEquals( i, tuple.getColumn( ParameterDataLinkInitialiser.PARAMETER_TUPLE_COL_SEQ_NUM ) ); long gentime = ((Long)tuple.getColumn( ParameterDataLinkInitialiser.PARAMETER_TUPLE_COL_GENTIME )).longValue(); long rectime = ((Long)tuple.getColumn( ParameterDataLinkInitialiser.PARAMETER_TUPLE_COL_RECTIME )).longValue(); assertEquals( gentime, rectime - 10, 0.0001 ); } assertEquals(numMessages, hornetReceivedCounter.get()); streamAdapter.quit(); ppRecorder.stopAsync(); msgClient.close(); ys.close(); } }