mirror of
https://github.com/wpilibsuite/allwpilib
synced 2026-07-02 02:51:42 +00:00
[datalog] Move all DataLog functionality to new datalog library (#7641)
Currently the major DataLog backend API (reading and writing) is split between wpiutil and glass. In the interest of allowing code that wants to use these APIs to not need to link to glass and declutter wpiutil, all of those APIs are moved to a new library named "datalog". Signed-off-by: Jade Turner <spacey-sooty@proton.me> Co-authored-by: Jade Turner <spacey-sooty@proton.me> Co-authored-by: Gold856 <117957790+Gold856@users.noreply.github.com>
This commit is contained in:
799
datalog/src/test/java/edu/wpi/first/datalog/DataLogTest.java
Normal file
799
datalog/src/test/java/edu/wpi/first/datalog/DataLogTest.java
Normal file
@@ -0,0 +1,799 @@
|
||||
// Copyright (c) FIRST and other WPILib contributors.
|
||||
// Open Source Software; you can modify and/or share it under the terms of
|
||||
// the WPILib BSD license file in the root directory of this project.
|
||||
|
||||
package edu.wpi.first.datalog;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertArrayEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
import edu.wpi.first.util.struct.Struct;
|
||||
import edu.wpi.first.util.struct.StructSerializable;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.Objects;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
@SuppressWarnings("AvoidEscapedUnicodeCharacters")
|
||||
class DataLogTest {
|
||||
static class ImmutableThingStruct implements Struct<ImmutableThing> {
|
||||
@Override
|
||||
public Class<ImmutableThing> getTypeClass() {
|
||||
return ImmutableThing.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTypeName() {
|
||||
return "Thing";
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSize() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSchema() {
|
||||
return "uint8 value";
|
||||
}
|
||||
|
||||
@Override
|
||||
public ImmutableThing unpack(ByteBuffer bb) {
|
||||
return new ImmutableThing(bb.get());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void pack(ByteBuffer bb, ImmutableThing value) {
|
||||
bb.put(value.m_x);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isImmutable() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
static class ImmutableThing implements StructSerializable {
|
||||
byte m_x;
|
||||
|
||||
ImmutableThing(int x) {
|
||||
m_x = (byte) x;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
return obj instanceof ImmutableThing other && other.m_x == m_x;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(m_x);
|
||||
}
|
||||
|
||||
public static final ImmutableThingStruct struct = new ImmutableThingStruct();
|
||||
}
|
||||
|
||||
static class CloneableThingStruct implements Struct<CloneableThing> {
|
||||
@Override
|
||||
public Class<CloneableThing> getTypeClass() {
|
||||
return CloneableThing.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTypeName() {
|
||||
return "Thing";
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSize() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSchema() {
|
||||
return "uint8 value";
|
||||
}
|
||||
|
||||
@Override
|
||||
public CloneableThing unpack(ByteBuffer bb) {
|
||||
return new CloneableThing(bb.get());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void pack(ByteBuffer bb, CloneableThing value) {
|
||||
bb.put(value.m_x);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCloneable() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CloneableThing clone(CloneableThing obj) throws CloneNotSupportedException {
|
||||
return obj.clone();
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("MemberName")
|
||||
private static int cloneCalls;
|
||||
|
||||
static class CloneableThing implements StructSerializable, Cloneable {
|
||||
byte m_x;
|
||||
|
||||
CloneableThing(int x) {
|
||||
m_x = (byte) x;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
return obj instanceof CloneableThing other && other.m_x == m_x;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(m_x);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CloneableThing clone() throws CloneNotSupportedException {
|
||||
CloneableThing thing = (CloneableThing) super.clone();
|
||||
cloneCalls++;
|
||||
return thing;
|
||||
}
|
||||
|
||||
public static final CloneableThingStruct struct = new CloneableThingStruct();
|
||||
}
|
||||
|
||||
static class ThingStruct implements Struct<Thing> {
|
||||
@Override
|
||||
public Class<Thing> getTypeClass() {
|
||||
return Thing.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTypeName() {
|
||||
return "Thing";
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSize() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSchema() {
|
||||
return "uint8 value";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Thing unpack(ByteBuffer bb) {
|
||||
return new Thing(bb.get());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void pack(ByteBuffer bb, Thing value) {
|
||||
bb.put(value.m_x);
|
||||
}
|
||||
}
|
||||
|
||||
static class Thing implements StructSerializable {
|
||||
byte m_x;
|
||||
|
||||
Thing(int x) {
|
||||
m_x = (byte) x;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
return obj instanceof Thing other && other.m_x == m_x;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(m_x);
|
||||
}
|
||||
|
||||
public static final ThingStruct struct = new ThingStruct();
|
||||
}
|
||||
|
||||
@SuppressWarnings("MemberName")
|
||||
private ByteArrayOutputStream data;
|
||||
|
||||
@SuppressWarnings("MemberName")
|
||||
private DataLog log;
|
||||
|
||||
@BeforeEach
|
||||
public void init() {
|
||||
data = new ByteArrayOutputStream();
|
||||
log = new DataLogWriter(data);
|
||||
cloneCalls = 0;
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
public void shutdown() {
|
||||
log.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSimpleInt() {
|
||||
int entry = log.start("test", "int64", "", 1);
|
||||
log.appendInteger(entry, 1, 2);
|
||||
log.flush();
|
||||
assertEquals(54, data.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testBooleanAppend() {
|
||||
BooleanLogEntry entry = new BooleanLogEntry(log, "a", 5);
|
||||
entry.append(false, 7);
|
||||
log.flush();
|
||||
assertEquals(46, data.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testBooleanUpdate() {
|
||||
BooleanLogEntry entry = new BooleanLogEntry(log, "a", 5);
|
||||
assertFalse(entry.hasLastValue());
|
||||
entry.update(false, 7);
|
||||
log.flush();
|
||||
assertEquals(46, data.size());
|
||||
assertTrue(entry.hasLastValue());
|
||||
assertFalse(entry.getLastValue());
|
||||
entry.update(false, 8);
|
||||
log.flush();
|
||||
assertEquals(46, data.size());
|
||||
entry.update(true, 9);
|
||||
log.flush();
|
||||
assertEquals(51, data.size());
|
||||
assertTrue(entry.hasLastValue());
|
||||
assertTrue(entry.getLastValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testIntegerAppend() {
|
||||
IntegerLogEntry entry = new IntegerLogEntry(log, "a", 5);
|
||||
entry.append(5, 7);
|
||||
log.flush();
|
||||
assertEquals(51, data.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testIntegerUpdate() {
|
||||
IntegerLogEntry entry = new IntegerLogEntry(log, "a", 5);
|
||||
assertFalse(entry.hasLastValue());
|
||||
entry.update(0, 7);
|
||||
log.flush();
|
||||
assertEquals(51, data.size());
|
||||
assertTrue(entry.hasLastValue());
|
||||
assertEquals(0, entry.getLastValue());
|
||||
entry.update(0, 8);
|
||||
log.flush();
|
||||
assertEquals(51, data.size());
|
||||
entry.update(2, 9);
|
||||
log.flush();
|
||||
assertEquals(63, data.size());
|
||||
assertTrue(entry.hasLastValue());
|
||||
assertEquals(2, entry.getLastValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testFloatAppend() {
|
||||
FloatLogEntry entry = new FloatLogEntry(log, "a", 5);
|
||||
entry.append(5.0f, 7);
|
||||
log.flush();
|
||||
assertEquals(47, data.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testFloatUpdate() {
|
||||
FloatLogEntry entry = new FloatLogEntry(log, "a", 5);
|
||||
assertFalse(entry.hasLastValue());
|
||||
entry.update(0.0f, 7);
|
||||
log.flush();
|
||||
assertEquals(47, data.size());
|
||||
assertTrue(entry.hasLastValue());
|
||||
assertEquals(0.0f, entry.getLastValue());
|
||||
entry.update(0.0f, 8);
|
||||
log.flush();
|
||||
assertEquals(47, data.size());
|
||||
entry.update(0.1f, 9);
|
||||
log.flush();
|
||||
assertEquals(55, data.size());
|
||||
assertTrue(entry.hasLastValue());
|
||||
assertEquals(0.1f, entry.getLastValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testDoubleAppend() {
|
||||
DoubleLogEntry entry = new DoubleLogEntry(log, "a", 5);
|
||||
entry.append(5.0, 7);
|
||||
log.flush();
|
||||
assertEquals(52, data.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testDoubleUpdate() {
|
||||
DoubleLogEntry entry = new DoubleLogEntry(log, "a", 5);
|
||||
assertFalse(entry.hasLastValue());
|
||||
entry.update(0.0, 7);
|
||||
log.flush();
|
||||
assertEquals(52, data.size());
|
||||
assertTrue(entry.hasLastValue());
|
||||
assertEquals(0.0, entry.getLastValue());
|
||||
entry.update(0.0, 8);
|
||||
log.flush();
|
||||
assertEquals(52, data.size());
|
||||
entry.update(0.1, 9);
|
||||
log.flush();
|
||||
assertEquals(64, data.size());
|
||||
assertTrue(entry.hasLastValue());
|
||||
assertEquals(0.1, entry.getLastValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testStringAppend() {
|
||||
StringLogEntry entry = new StringLogEntry(log, "a", 5);
|
||||
entry.append("x", 7);
|
||||
log.flush();
|
||||
assertEquals(45, data.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testStringUpdate() {
|
||||
StringLogEntry entry = new StringLogEntry(log, "a", 5);
|
||||
assertFalse(entry.hasLastValue());
|
||||
|
||||
entry.update("x", 7);
|
||||
log.flush();
|
||||
assertEquals(45, data.size());
|
||||
assertTrue(entry.hasLastValue());
|
||||
assertEquals("x", entry.getLastValue());
|
||||
|
||||
entry.update("x", 8);
|
||||
log.flush();
|
||||
assertEquals(45, data.size());
|
||||
|
||||
entry.update("y", 9);
|
||||
log.flush();
|
||||
assertEquals(50, data.size());
|
||||
assertTrue(entry.hasLastValue());
|
||||
assertEquals("y", entry.getLastValue());
|
||||
|
||||
entry.update("yy", 10);
|
||||
log.flush();
|
||||
assertEquals(56, data.size());
|
||||
assertTrue(entry.hasLastValue());
|
||||
assertEquals("yy", entry.getLastValue());
|
||||
|
||||
entry.update("", 11);
|
||||
log.flush();
|
||||
assertEquals(60, data.size());
|
||||
assertTrue(entry.hasLastValue());
|
||||
assertEquals("", entry.getLastValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testRawAppend() {
|
||||
RawLogEntry entry = new RawLogEntry(log, "a", 5);
|
||||
entry.append(new byte[] {5}, 7);
|
||||
log.flush();
|
||||
assertEquals(42, data.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testRawUpdate() {
|
||||
RawLogEntry entry = new RawLogEntry(log, "a", 5);
|
||||
assertFalse(entry.hasLastValue());
|
||||
|
||||
entry.update(new byte[] {5}, 7);
|
||||
log.flush();
|
||||
assertEquals(42, data.size());
|
||||
assertTrue(entry.hasLastValue());
|
||||
assertArrayEquals(new byte[] {5}, entry.getLastValue());
|
||||
|
||||
entry.update(new byte[] {5}, 8);
|
||||
log.flush();
|
||||
assertEquals(42, data.size());
|
||||
|
||||
entry.update(new byte[] {6}, 9);
|
||||
log.flush();
|
||||
assertEquals(47, data.size());
|
||||
assertTrue(entry.hasLastValue());
|
||||
assertArrayEquals(new byte[] {6}, entry.getLastValue());
|
||||
|
||||
entry.update(new byte[] {6, 6}, 10);
|
||||
log.flush();
|
||||
assertEquals(53, data.size());
|
||||
assertTrue(entry.hasLastValue());
|
||||
assertArrayEquals(new byte[] {6, 6}, entry.getLastValue());
|
||||
|
||||
entry.update(new byte[] {}, 11);
|
||||
log.flush();
|
||||
assertEquals(57, data.size());
|
||||
assertTrue(entry.hasLastValue());
|
||||
assertArrayEquals(new byte[] {}, entry.getLastValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testBooleanArrayAppendEmpty() {
|
||||
BooleanArrayLogEntry entry = new BooleanArrayLogEntry(log, "a", 5);
|
||||
entry.append(new boolean[] {}, 7);
|
||||
log.flush();
|
||||
assertEquals(47, data.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testBooleanArrayAppend() {
|
||||
BooleanArrayLogEntry entry = new BooleanArrayLogEntry(log, "a", 5);
|
||||
entry.append(new boolean[] {false}, 7);
|
||||
log.flush();
|
||||
assertEquals(48, data.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testBooleanArrayUpdate() {
|
||||
BooleanArrayLogEntry entry = new BooleanArrayLogEntry(log, "a", 5);
|
||||
assertFalse(entry.hasLastValue());
|
||||
entry.update(new boolean[] {false}, 7);
|
||||
log.flush();
|
||||
assertEquals(48, data.size());
|
||||
assertTrue(entry.hasLastValue());
|
||||
assertArrayEquals(new boolean[] {false}, entry.getLastValue());
|
||||
entry.update(new boolean[] {false}, 8);
|
||||
log.flush();
|
||||
assertEquals(48, data.size());
|
||||
entry.update(new boolean[] {true}, 9);
|
||||
log.flush();
|
||||
assertEquals(53, data.size());
|
||||
assertTrue(entry.hasLastValue());
|
||||
assertArrayEquals(new boolean[] {true}, entry.getLastValue());
|
||||
entry.update(new boolean[] {}, 10);
|
||||
log.flush();
|
||||
assertEquals(57, data.size());
|
||||
assertTrue(entry.hasLastValue());
|
||||
assertArrayEquals(new boolean[] {}, entry.getLastValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testIntegerArrayAppendEmpty() {
|
||||
IntegerArrayLogEntry entry = new IntegerArrayLogEntry(log, "a", 5);
|
||||
entry.append(new long[] {}, 7);
|
||||
log.flush();
|
||||
assertEquals(45, data.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testIntegerArrayAppend() {
|
||||
IntegerArrayLogEntry entry = new IntegerArrayLogEntry(log, "a", 5);
|
||||
entry.append(new long[] {1}, 7);
|
||||
log.flush();
|
||||
assertEquals(53, data.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testIntegerArrayUpdate() {
|
||||
IntegerArrayLogEntry entry = new IntegerArrayLogEntry(log, "a", 5);
|
||||
assertFalse(entry.hasLastValue());
|
||||
entry.update(new long[] {1}, 7);
|
||||
log.flush();
|
||||
assertEquals(53, data.size());
|
||||
assertTrue(entry.hasLastValue());
|
||||
assertArrayEquals(new long[] {1}, entry.getLastValue());
|
||||
entry.update(new long[] {1}, 8);
|
||||
log.flush();
|
||||
assertEquals(53, data.size());
|
||||
entry.update(new long[] {2}, 9);
|
||||
log.flush();
|
||||
assertEquals(65, data.size());
|
||||
assertTrue(entry.hasLastValue());
|
||||
assertArrayEquals(new long[] {2}, entry.getLastValue());
|
||||
entry.update(new long[] {}, 10);
|
||||
log.flush();
|
||||
assertEquals(69, data.size());
|
||||
assertTrue(entry.hasLastValue());
|
||||
assertArrayEquals(new long[] {}, entry.getLastValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testDoubleArrayAppendEmpty() {
|
||||
DoubleArrayLogEntry entry = new DoubleArrayLogEntry(log, "a", 5);
|
||||
entry.append(new double[] {}, 7);
|
||||
log.flush();
|
||||
assertEquals(46, data.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testDoubleArrayAppend() {
|
||||
DoubleArrayLogEntry entry = new DoubleArrayLogEntry(log, "a", 5);
|
||||
entry.append(new double[] {1.0}, 7);
|
||||
log.flush();
|
||||
assertEquals(54, data.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testDoubleArrayUpdate() {
|
||||
DoubleArrayLogEntry entry = new DoubleArrayLogEntry(log, "a", 5);
|
||||
assertFalse(entry.hasLastValue());
|
||||
entry.update(new double[] {1.0}, 7);
|
||||
log.flush();
|
||||
assertEquals(54, data.size());
|
||||
assertTrue(entry.hasLastValue());
|
||||
assertArrayEquals(new double[] {1.0}, entry.getLastValue());
|
||||
entry.update(new double[] {1.0}, 8);
|
||||
log.flush();
|
||||
assertEquals(54, data.size());
|
||||
entry.update(new double[] {2.0}, 9);
|
||||
log.flush();
|
||||
assertEquals(66, data.size());
|
||||
assertTrue(entry.hasLastValue());
|
||||
assertArrayEquals(new double[] {2}, entry.getLastValue());
|
||||
entry.update(new double[] {}, 10);
|
||||
log.flush();
|
||||
assertEquals(70, data.size());
|
||||
assertTrue(entry.hasLastValue());
|
||||
assertArrayEquals(new double[] {}, entry.getLastValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testFloatArrayAppendEmpty() {
|
||||
FloatArrayLogEntry entry = new FloatArrayLogEntry(log, "a", 5);
|
||||
entry.append(new float[] {}, 7);
|
||||
log.flush();
|
||||
assertEquals(45, data.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testFloatArrayAppend() {
|
||||
FloatArrayLogEntry entry = new FloatArrayLogEntry(log, "a", 5);
|
||||
entry.append(new float[] {1.0f}, 7);
|
||||
log.flush();
|
||||
assertEquals(49, data.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testFloatArrayUpdate() {
|
||||
FloatArrayLogEntry entry = new FloatArrayLogEntry(log, "a", 5);
|
||||
assertFalse(entry.hasLastValue());
|
||||
entry.update(new float[] {1.0f}, 7);
|
||||
log.flush();
|
||||
assertEquals(49, data.size());
|
||||
assertTrue(entry.hasLastValue());
|
||||
assertArrayEquals(new float[] {1.0f}, entry.getLastValue());
|
||||
entry.update(new float[] {1.0f}, 8);
|
||||
log.flush();
|
||||
assertEquals(49, data.size());
|
||||
entry.update(new float[] {2.0f}, 9);
|
||||
log.flush();
|
||||
assertEquals(57, data.size());
|
||||
assertTrue(entry.hasLastValue());
|
||||
assertArrayEquals(new float[] {2.0f}, entry.getLastValue());
|
||||
entry.update(new float[] {}, 10);
|
||||
log.flush();
|
||||
assertEquals(61, data.size());
|
||||
assertTrue(entry.hasLastValue());
|
||||
assertArrayEquals(new float[] {}, entry.getLastValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testStringArrayAppendEmpty() {
|
||||
StringArrayLogEntry entry = new StringArrayLogEntry(log, "a", 5);
|
||||
entry.append(new String[] {}, 7);
|
||||
entry.append(new String[] {}, 7);
|
||||
log.flush();
|
||||
assertEquals(58, data.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testStringArrayAppend() {
|
||||
StringArrayLogEntry entry = new StringArrayLogEntry(log, "a", 5);
|
||||
entry.append(new String[] {"x"}, 7);
|
||||
log.flush();
|
||||
assertEquals(55, data.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testStringArrayUpdate() {
|
||||
StringArrayLogEntry entry = new StringArrayLogEntry(log, "a", 5);
|
||||
assertFalse(entry.hasLastValue());
|
||||
entry.update(new String[] {"x"}, 7);
|
||||
log.flush();
|
||||
assertEquals(55, data.size());
|
||||
assertTrue(entry.hasLastValue());
|
||||
assertArrayEquals(new String[] {"x"}, entry.getLastValue());
|
||||
entry.update(new String[] {"x"}, 8);
|
||||
log.flush();
|
||||
assertEquals(55, data.size());
|
||||
entry.update(new String[] {"y"}, 9);
|
||||
log.flush();
|
||||
assertEquals(68, data.size());
|
||||
assertTrue(entry.hasLastValue());
|
||||
assertArrayEquals(new String[] {"y"}, entry.getLastValue());
|
||||
entry.update(new String[] {}, 10);
|
||||
log.flush();
|
||||
assertEquals(76, data.size());
|
||||
assertTrue(entry.hasLastValue());
|
||||
assertArrayEquals(new String[] {}, entry.getLastValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testStruct() {
|
||||
StructLogEntry<Thing> entry = StructLogEntry.create(log, "a", Thing.struct, 5);
|
||||
entry.append(new Thing((byte) 1), 6);
|
||||
entry.append(new Thing((byte) 0), 7);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testStructUpdate() {
|
||||
StructLogEntry<Thing> entry = StructLogEntry.create(log, "a", Thing.struct, 5);
|
||||
assertFalse(entry.hasLastValue());
|
||||
|
||||
entry.update(new Thing(1), 7);
|
||||
log.flush();
|
||||
assertEquals(120, data.size());
|
||||
assertTrue(entry.hasLastValue());
|
||||
assertEquals(new Thing(1), entry.getLastValue());
|
||||
|
||||
entry.update(new Thing(1), 8);
|
||||
log.flush();
|
||||
assertEquals(120, data.size());
|
||||
|
||||
entry.update(new Thing(2), 9);
|
||||
log.flush();
|
||||
assertEquals(125, data.size());
|
||||
assertTrue(entry.hasLastValue());
|
||||
assertEquals(new Thing(2), entry.getLastValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testCloneableStructUpdate() {
|
||||
StructLogEntry<CloneableThing> entry =
|
||||
StructLogEntry.create(log, "a", CloneableThing.struct, 5);
|
||||
assertFalse(entry.hasLastValue());
|
||||
|
||||
entry.update(new CloneableThing(1), 7);
|
||||
assertEquals(1, cloneCalls);
|
||||
log.flush();
|
||||
assertEquals(120, data.size());
|
||||
assertTrue(entry.hasLastValue());
|
||||
assertEquals(new CloneableThing(1), entry.getLastValue());
|
||||
assertEquals(2, cloneCalls);
|
||||
|
||||
entry.update(new CloneableThing(1), 8);
|
||||
assertEquals(2, cloneCalls);
|
||||
log.flush();
|
||||
assertEquals(120, data.size());
|
||||
|
||||
entry.update(new CloneableThing(2), 9);
|
||||
assertEquals(3, cloneCalls);
|
||||
log.flush();
|
||||
assertEquals(125, data.size());
|
||||
assertTrue(entry.hasLastValue());
|
||||
assertEquals(new CloneableThing(2), entry.getLastValue());
|
||||
assertEquals(4, cloneCalls);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testImmutableStructUpdate() {
|
||||
StructLogEntry<ImmutableThing> entry =
|
||||
StructLogEntry.create(log, "a", ImmutableThing.struct, 5);
|
||||
assertFalse(entry.hasLastValue());
|
||||
|
||||
entry.update(new ImmutableThing(1), 7);
|
||||
log.flush();
|
||||
assertEquals(120, data.size());
|
||||
assertTrue(entry.hasLastValue());
|
||||
assertEquals(new ImmutableThing(1), entry.getLastValue());
|
||||
|
||||
entry.update(new ImmutableThing(1), 8);
|
||||
log.flush();
|
||||
assertEquals(120, data.size());
|
||||
|
||||
entry.update(new ImmutableThing(2), 9);
|
||||
log.flush();
|
||||
assertEquals(125, data.size());
|
||||
assertTrue(entry.hasLastValue());
|
||||
assertEquals(new ImmutableThing(2), entry.getLastValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testStructArrayUpdate() {
|
||||
StructArrayLogEntry<Thing> entry = StructArrayLogEntry.create(log, "a", Thing.struct, 5);
|
||||
assertFalse(entry.hasLastValue());
|
||||
|
||||
entry.update(new Thing[] {new Thing(1), new Thing(2)}, 7);
|
||||
log.flush();
|
||||
assertEquals(123, data.size());
|
||||
assertTrue(entry.hasLastValue());
|
||||
assertArrayEquals(new Thing[] {new Thing(1), new Thing(2)}, entry.getLastValue());
|
||||
|
||||
entry.update(new Thing[] {new Thing(1), new Thing(2)}, 8);
|
||||
log.flush();
|
||||
assertEquals(123, data.size());
|
||||
|
||||
entry.update(new Thing[] {new Thing(1), new Thing(3)}, 9);
|
||||
log.flush();
|
||||
assertEquals(129, data.size());
|
||||
assertTrue(entry.hasLastValue());
|
||||
assertArrayEquals(new Thing[] {new Thing(1), new Thing(3)}, entry.getLastValue());
|
||||
|
||||
entry.update(new Thing[] {}, 10);
|
||||
log.flush();
|
||||
assertEquals(133, data.size());
|
||||
assertTrue(entry.hasLastValue());
|
||||
assertArrayEquals(new Thing[] {}, entry.getLastValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testCloneableStructArrayUpdate() {
|
||||
StructArrayLogEntry<CloneableThing> entry =
|
||||
StructArrayLogEntry.create(log, "a", CloneableThing.struct, 5);
|
||||
assertFalse(entry.hasLastValue());
|
||||
|
||||
entry.update(new CloneableThing[] {new CloneableThing(1), new CloneableThing(2)}, 7);
|
||||
assertEquals(2, cloneCalls);
|
||||
log.flush();
|
||||
assertEquals(123, data.size());
|
||||
assertTrue(entry.hasLastValue());
|
||||
assertArrayEquals(
|
||||
new CloneableThing[] {new CloneableThing(1), new CloneableThing(2)}, entry.getLastValue());
|
||||
assertEquals(4, cloneCalls);
|
||||
|
||||
entry.update(new CloneableThing[] {new CloneableThing(1), new CloneableThing(2)}, 8);
|
||||
assertEquals(4, cloneCalls);
|
||||
log.flush();
|
||||
assertEquals(123, data.size());
|
||||
|
||||
entry.update(new CloneableThing[] {new CloneableThing(1), new CloneableThing(3)}, 9);
|
||||
assertEquals(6, cloneCalls);
|
||||
log.flush();
|
||||
assertEquals(129, data.size());
|
||||
assertTrue(entry.hasLastValue());
|
||||
assertArrayEquals(
|
||||
new CloneableThing[] {new CloneableThing(1), new CloneableThing(3)}, entry.getLastValue());
|
||||
assertEquals(8, cloneCalls);
|
||||
|
||||
entry.update(new CloneableThing[] {}, 10);
|
||||
assertEquals(8, cloneCalls);
|
||||
log.flush();
|
||||
assertEquals(133, data.size());
|
||||
assertTrue(entry.hasLastValue());
|
||||
assertArrayEquals(new CloneableThing[] {}, entry.getLastValue());
|
||||
assertEquals(8, cloneCalls);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testImmutableStructArrayUpdate() {
|
||||
StructArrayLogEntry<ImmutableThing> entry =
|
||||
StructArrayLogEntry.create(log, "a", ImmutableThing.struct, 5);
|
||||
assertFalse(entry.hasLastValue());
|
||||
|
||||
entry.update(new ImmutableThing[] {new ImmutableThing(1), new ImmutableThing(2)}, 7);
|
||||
log.flush();
|
||||
assertEquals(123, data.size());
|
||||
assertTrue(entry.hasLastValue());
|
||||
assertArrayEquals(
|
||||
new ImmutableThing[] {new ImmutableThing(1), new ImmutableThing(2)}, entry.getLastValue());
|
||||
|
||||
entry.update(new ImmutableThing[] {new ImmutableThing(1), new ImmutableThing(2)}, 8);
|
||||
log.flush();
|
||||
assertEquals(123, data.size());
|
||||
|
||||
entry.update(new ImmutableThing[] {new ImmutableThing(1), new ImmutableThing(3)}, 9);
|
||||
log.flush();
|
||||
assertEquals(129, data.size());
|
||||
assertTrue(entry.hasLastValue());
|
||||
assertArrayEquals(
|
||||
new ImmutableThing[] {new ImmutableThing(1), new ImmutableThing(3)}, entry.getLastValue());
|
||||
|
||||
entry.update(new ImmutableThing[] {}, 10);
|
||||
log.flush();
|
||||
assertEquals(133, data.size());
|
||||
assertTrue(entry.hasLastValue());
|
||||
assertArrayEquals(new ImmutableThing[] {}, entry.getLastValue());
|
||||
}
|
||||
}
|
||||
674
datalog/src/test/native/cpp/DataLogTest.cpp
Normal file
674
datalog/src/test/native/cpp/DataLogTest.cpp
Normal file
@@ -0,0 +1,674 @@
|
||||
// Copyright (c) FIRST and other WPILib contributors.
|
||||
// Open Source Software; you can modify and/or share it under the terms of
|
||||
// the WPILib BSD license file in the root directory of this project.
|
||||
|
||||
#include <array>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <wpi/Logger.h>
|
||||
#include <wpi/raw_ostream.h>
|
||||
|
||||
#include "wpi/datalog/DataLogWriter.h"
|
||||
|
||||
namespace {
|
||||
struct ThingA {
|
||||
int x = 0;
|
||||
};
|
||||
|
||||
inline bool operator==(const ThingA& a, const ThingA& b) {
|
||||
return a.x == b.x;
|
||||
}
|
||||
|
||||
struct ThingB {
|
||||
int x = 0;
|
||||
};
|
||||
|
||||
struct ThingC {
|
||||
int x = 0;
|
||||
};
|
||||
|
||||
struct Info1 {
|
||||
int info = 0;
|
||||
};
|
||||
|
||||
struct Info2 {
|
||||
int info = 0;
|
||||
};
|
||||
} // namespace
|
||||
|
||||
template <>
|
||||
struct wpi::Struct<ThingA> {
|
||||
static constexpr std::string_view GetTypeName() { return "ThingA"; }
|
||||
static constexpr size_t GetSize() { return 1; }
|
||||
static constexpr std::string_view GetSchema() { return "uint8 value"; }
|
||||
static ThingA Unpack(std::span<const uint8_t> data) {
|
||||
return ThingA{.x = data[0]};
|
||||
}
|
||||
static void Pack(std::span<uint8_t> data, const ThingA& value) {
|
||||
data[0] = value.x;
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct wpi::Struct<ThingB, Info1> {
|
||||
static constexpr std::string_view GetTypeName(const Info1&) {
|
||||
return "ThingB";
|
||||
}
|
||||
static constexpr size_t GetSize(const Info1&) { return 1; }
|
||||
static constexpr std::string_view GetSchema(const Info1&) {
|
||||
return "uint8 value";
|
||||
}
|
||||
static ThingB Unpack(std::span<const uint8_t> data, const Info1&) {
|
||||
return ThingB{.x = data[0]};
|
||||
}
|
||||
static void Pack(std::span<uint8_t> data, const ThingB& value, const Info1&) {
|
||||
data[0] = value.x;
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct wpi::Struct<ThingC> {
|
||||
static constexpr std::string_view GetTypeName() { return "ThingC"; }
|
||||
static constexpr size_t GetSize() { return 1; }
|
||||
static constexpr std::string_view GetSchema() { return "uint8 value"; }
|
||||
static ThingC Unpack(std::span<const uint8_t> data) {
|
||||
return ThingC{.x = data[0]};
|
||||
}
|
||||
static void Pack(std::span<uint8_t> data, const ThingC& value) {
|
||||
data[0] = value.x;
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct wpi::Struct<ThingC, Info1> {
|
||||
static constexpr std::string_view GetTypeName(const Info1&) {
|
||||
return "ThingC";
|
||||
}
|
||||
static constexpr size_t GetSize(const Info1&) { return 1; }
|
||||
static constexpr std::string_view GetSchema(const Info1&) {
|
||||
return "uint8 value";
|
||||
}
|
||||
static ThingC Unpack(std::span<const uint8_t> data, const Info1&) {
|
||||
return ThingC{.x = data[0]};
|
||||
}
|
||||
static void Pack(std::span<uint8_t> data, const ThingC& value, const Info1&) {
|
||||
data[0] = value.x;
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct wpi::Struct<ThingC, Info2> {
|
||||
static constexpr std::string_view GetTypeName(const Info2&) {
|
||||
return "ThingC";
|
||||
}
|
||||
static constexpr size_t GetSize(const Info2&) { return 1; }
|
||||
static constexpr std::string_view GetSchema(const Info2&) {
|
||||
return "uint8 value";
|
||||
}
|
||||
static ThingC Unpack(std::span<const uint8_t> data, const Info2&) {
|
||||
return ThingC{.x = data[0]};
|
||||
}
|
||||
static void Pack(std::span<uint8_t> data, const ThingC& value, const Info2&) {
|
||||
data[0] = value.x;
|
||||
}
|
||||
};
|
||||
|
||||
static_assert(wpi::StructSerializable<ThingA>);
|
||||
static_assert(!wpi::StructSerializable<ThingA, Info1>);
|
||||
|
||||
static_assert(!wpi::StructSerializable<ThingB>);
|
||||
static_assert(wpi::StructSerializable<ThingB, Info1>);
|
||||
static_assert(!wpi::StructSerializable<ThingB, Info2>);
|
||||
|
||||
static_assert(wpi::StructSerializable<ThingC>);
|
||||
static_assert(wpi::StructSerializable<ThingC, Info1>);
|
||||
static_assert(wpi::StructSerializable<ThingC, Info2>);
|
||||
|
||||
class DataLogTest : public ::testing::Test {
|
||||
public:
|
||||
wpi::Logger msglog;
|
||||
std::vector<uint8_t> data;
|
||||
wpi::log::DataLogWriter log{msglog,
|
||||
std::make_unique<wpi::raw_uvector_ostream>(data)};
|
||||
};
|
||||
|
||||
TEST_F(DataLogTest, SimpleInt) {
|
||||
int entry = log.Start("test", "int64", "", 1);
|
||||
log.AppendInteger(entry, 1, 2);
|
||||
log.Flush();
|
||||
ASSERT_EQ(data.size(), 54u);
|
||||
}
|
||||
|
||||
TEST_F(DataLogTest, BooleanAppend) {
|
||||
wpi::log::BooleanLogEntry entry{log, "a", 5};
|
||||
entry.Append(false, 7);
|
||||
log.Flush();
|
||||
ASSERT_EQ(data.size(), 46u);
|
||||
}
|
||||
|
||||
TEST_F(DataLogTest, BooleanUpdate) {
|
||||
wpi::log::BooleanLogEntry entry{log, "a", 5};
|
||||
ASSERT_FALSE(entry.GetLastValue().has_value());
|
||||
entry.Update(false, 7);
|
||||
log.Flush();
|
||||
ASSERT_EQ(data.size(), 46u);
|
||||
ASSERT_TRUE(entry.GetLastValue().has_value());
|
||||
ASSERT_EQ(entry.GetLastValue().value(), false);
|
||||
entry.Update(false, 8);
|
||||
log.Flush();
|
||||
ASSERT_EQ(data.size(), 46u);
|
||||
entry.Update(true, 9);
|
||||
log.Flush();
|
||||
ASSERT_EQ(data.size(), 51u);
|
||||
ASSERT_TRUE(entry.GetLastValue().has_value());
|
||||
ASSERT_EQ(entry.GetLastValue().value(), true);
|
||||
}
|
||||
|
||||
TEST_F(DataLogTest, IntegerAppend) {
|
||||
wpi::log::IntegerLogEntry entry{log, "a", 5};
|
||||
entry.Append(5, 7);
|
||||
log.Flush();
|
||||
ASSERT_EQ(data.size(), 51u);
|
||||
}
|
||||
|
||||
TEST_F(DataLogTest, IntegerUpdate) {
|
||||
wpi::log::IntegerLogEntry entry{log, "a", 5};
|
||||
ASSERT_FALSE(entry.GetLastValue().has_value());
|
||||
entry.Update(0, 7);
|
||||
log.Flush();
|
||||
ASSERT_EQ(data.size(), 51u);
|
||||
ASSERT_TRUE(entry.GetLastValue().has_value());
|
||||
ASSERT_EQ(entry.GetLastValue().value(), 0);
|
||||
entry.Update(0, 8);
|
||||
log.Flush();
|
||||
ASSERT_EQ(data.size(), 51u);
|
||||
entry.Update(2, 9);
|
||||
log.Flush();
|
||||
ASSERT_EQ(data.size(), 63u);
|
||||
ASSERT_TRUE(entry.GetLastValue().has_value());
|
||||
ASSERT_EQ(entry.GetLastValue().value(), 2);
|
||||
}
|
||||
|
||||
TEST_F(DataLogTest, FloatAppend) {
|
||||
wpi::log::FloatLogEntry entry{log, "a", 5};
|
||||
entry.Append(5.0, 7);
|
||||
log.Flush();
|
||||
ASSERT_EQ(data.size(), 47u);
|
||||
}
|
||||
|
||||
TEST_F(DataLogTest, FloatUpdate) {
|
||||
wpi::log::FloatLogEntry entry{log, "a", 5};
|
||||
ASSERT_FALSE(entry.GetLastValue().has_value());
|
||||
entry.Update(0.0f, 7);
|
||||
log.Flush();
|
||||
ASSERT_EQ(data.size(), 47u);
|
||||
ASSERT_TRUE(entry.GetLastValue().has_value());
|
||||
ASSERT_EQ(entry.GetLastValue().value(), 0.0f);
|
||||
entry.Update(0.0f, 8);
|
||||
log.Flush();
|
||||
ASSERT_EQ(data.size(), 47u);
|
||||
entry.Update(0.1f, 9);
|
||||
log.Flush();
|
||||
ASSERT_EQ(data.size(), 55u);
|
||||
ASSERT_TRUE(entry.GetLastValue().has_value());
|
||||
ASSERT_EQ(entry.GetLastValue().value(), 0.1f);
|
||||
}
|
||||
|
||||
TEST_F(DataLogTest, DoubleAppend) {
|
||||
wpi::log::DoubleLogEntry entry{log, "a", 5};
|
||||
entry.Append(5.0, 7);
|
||||
log.Flush();
|
||||
ASSERT_EQ(data.size(), 52u);
|
||||
}
|
||||
|
||||
TEST_F(DataLogTest, DoubleUpdate) {
|
||||
wpi::log::DoubleLogEntry entry{log, "a", 5};
|
||||
ASSERT_FALSE(entry.GetLastValue().has_value());
|
||||
entry.Update(0.0, 7);
|
||||
log.Flush();
|
||||
ASSERT_EQ(data.size(), 52u);
|
||||
ASSERT_TRUE(entry.GetLastValue().has_value());
|
||||
ASSERT_EQ(entry.GetLastValue().value(), 0.0);
|
||||
entry.Update(0.0, 8);
|
||||
log.Flush();
|
||||
ASSERT_EQ(data.size(), 52u);
|
||||
entry.Update(0.1, 9);
|
||||
log.Flush();
|
||||
ASSERT_EQ(data.size(), 64u);
|
||||
ASSERT_TRUE(entry.GetLastValue().has_value());
|
||||
ASSERT_EQ(entry.GetLastValue().value(), 0.1);
|
||||
}
|
||||
|
||||
TEST_F(DataLogTest, StringAppend) {
|
||||
wpi::log::StringLogEntry entry{log, "a", 5};
|
||||
entry.Append("x", 7);
|
||||
log.Flush();
|
||||
ASSERT_EQ(data.size(), 45u);
|
||||
}
|
||||
|
||||
TEST_F(DataLogTest, StringUpdate) {
|
||||
wpi::log::StringLogEntry entry{log, "a", 5};
|
||||
ASSERT_FALSE(entry.HasLastValue());
|
||||
|
||||
entry.Update("x", 7);
|
||||
log.Flush();
|
||||
ASSERT_EQ(data.size(), 45u);
|
||||
ASSERT_TRUE(entry.GetLastValue().has_value());
|
||||
ASSERT_EQ(entry.GetLastValue().value(), "x");
|
||||
|
||||
entry.Update("x", 8);
|
||||
log.Flush();
|
||||
ASSERT_EQ(data.size(), 45u);
|
||||
|
||||
entry.Update("y", 9);
|
||||
log.Flush();
|
||||
ASSERT_EQ(data.size(), 50u);
|
||||
ASSERT_TRUE(entry.GetLastValue().has_value());
|
||||
ASSERT_EQ(entry.GetLastValue().value(), "y");
|
||||
|
||||
entry.Update("yy", 10);
|
||||
log.Flush();
|
||||
ASSERT_EQ(data.size(), 56u);
|
||||
ASSERT_TRUE(entry.GetLastValue().has_value());
|
||||
ASSERT_EQ(entry.GetLastValue().value(), "yy");
|
||||
|
||||
entry.Update("", 11);
|
||||
log.Flush();
|
||||
ASSERT_EQ(data.size(), 60u);
|
||||
ASSERT_TRUE(entry.GetLastValue().has_value());
|
||||
ASSERT_EQ(entry.GetLastValue().value(), "");
|
||||
}
|
||||
|
||||
TEST_F(DataLogTest, RawAppend) {
|
||||
wpi::log::RawLogEntry entry{log, "a", 5};
|
||||
entry.Append({{5}}, 7);
|
||||
log.Flush();
|
||||
ASSERT_EQ(data.size(), 42u);
|
||||
}
|
||||
|
||||
TEST_F(DataLogTest, RawUpdate) {
|
||||
wpi::log::RawLogEntry entry{log, "a", 5};
|
||||
ASSERT_FALSE(entry.HasLastValue());
|
||||
|
||||
entry.Update({{5}}, 7);
|
||||
log.Flush();
|
||||
ASSERT_EQ(data.size(), 42u);
|
||||
ASSERT_TRUE(entry.GetLastValue().has_value());
|
||||
ASSERT_EQ(entry.GetLastValue().value(), std::vector<uint8_t>{5});
|
||||
|
||||
entry.Update({{5}}, 8);
|
||||
log.Flush();
|
||||
ASSERT_EQ(data.size(), 42u);
|
||||
|
||||
entry.Update({{6}}, 9);
|
||||
log.Flush();
|
||||
ASSERT_EQ(data.size(), 47u);
|
||||
ASSERT_TRUE(entry.GetLastValue().has_value());
|
||||
ASSERT_EQ(entry.GetLastValue().value(), std::vector<uint8_t>{6});
|
||||
|
||||
entry.Update({{6, 6}}, 9);
|
||||
log.Flush();
|
||||
ASSERT_EQ(data.size(), 53u);
|
||||
ASSERT_TRUE(entry.GetLastValue().has_value());
|
||||
ASSERT_EQ(entry.GetLastValue().value(), (std::vector<uint8_t>{6, 6}));
|
||||
|
||||
entry.Update(std::span<const uint8_t>{}, 10);
|
||||
log.Flush();
|
||||
ASSERT_EQ(data.size(), 57u);
|
||||
ASSERT_TRUE(entry.GetLastValue().has_value());
|
||||
ASSERT_EQ(entry.GetLastValue().value(), std::vector<uint8_t>{});
|
||||
}
|
||||
|
||||
TEST_F(DataLogTest, BooleanArrayAppendEmpty) {
|
||||
wpi::log::BooleanArrayLogEntry entry{log, "a", 5};
|
||||
entry.Append(std::span<const bool>{}, 7);
|
||||
log.Flush();
|
||||
ASSERT_EQ(data.size(), 47u);
|
||||
}
|
||||
|
||||
TEST_F(DataLogTest, BooleanArrayAppend) {
|
||||
wpi::log::BooleanArrayLogEntry entry{log, "a", 5};
|
||||
entry.Append({false}, 7);
|
||||
log.Flush();
|
||||
ASSERT_EQ(data.size(), 48u);
|
||||
}
|
||||
|
||||
TEST_F(DataLogTest, BooleanArrayUpdate) {
|
||||
wpi::log::BooleanArrayLogEntry entry{log, "a", 5};
|
||||
ASSERT_FALSE(entry.GetLastValue().has_value());
|
||||
entry.Update({false}, 7);
|
||||
log.Flush();
|
||||
ASSERT_EQ(data.size(), 48u);
|
||||
ASSERT_TRUE(entry.GetLastValue().has_value());
|
||||
ASSERT_EQ(entry.GetLastValue().value(), std::vector<int>{false});
|
||||
entry.Update({false}, 8);
|
||||
log.Flush();
|
||||
ASSERT_EQ(data.size(), 48u);
|
||||
entry.Update({true}, 9);
|
||||
log.Flush();
|
||||
ASSERT_EQ(data.size(), 53u);
|
||||
ASSERT_TRUE(entry.GetLastValue().has_value());
|
||||
ASSERT_EQ(entry.GetLastValue().value(), std::vector<int>{true});
|
||||
entry.Update(std::span<const bool>{}, 10);
|
||||
log.Flush();
|
||||
ASSERT_EQ(data.size(), 57u);
|
||||
ASSERT_TRUE(entry.GetLastValue().has_value());
|
||||
ASSERT_EQ(entry.GetLastValue().value(), std::vector<int>{});
|
||||
}
|
||||
|
||||
TEST_F(DataLogTest, IntegerArrayAppendEmpty) {
|
||||
wpi::log::IntegerArrayLogEntry entry{log, "a", 5};
|
||||
entry.Append(std::span<const int64_t>{}, 7);
|
||||
log.Flush();
|
||||
ASSERT_EQ(data.size(), 45u);
|
||||
}
|
||||
|
||||
TEST_F(DataLogTest, IntegerArrayAppend) {
|
||||
wpi::log::IntegerArrayLogEntry entry{log, "a", 5};
|
||||
entry.Append({1}, 7);
|
||||
log.Flush();
|
||||
ASSERT_EQ(data.size(), 53u);
|
||||
}
|
||||
|
||||
TEST_F(DataLogTest, IntegerArrayUpdate) {
|
||||
wpi::log::IntegerArrayLogEntry entry{log, "a", 5};
|
||||
ASSERT_FALSE(entry.GetLastValue().has_value());
|
||||
entry.Update({1}, 7);
|
||||
log.Flush();
|
||||
ASSERT_EQ(data.size(), 53u);
|
||||
ASSERT_TRUE(entry.GetLastValue().has_value());
|
||||
ASSERT_EQ(entry.GetLastValue().value(), std::vector<int64_t>{1});
|
||||
entry.Update({1}, 8);
|
||||
log.Flush();
|
||||
ASSERT_EQ(data.size(), 53u);
|
||||
entry.Update({2}, 9);
|
||||
log.Flush();
|
||||
ASSERT_EQ(data.size(), 65u);
|
||||
ASSERT_TRUE(entry.GetLastValue().has_value());
|
||||
ASSERT_EQ(entry.GetLastValue().value(), std::vector<int64_t>{2});
|
||||
entry.Update(std::span<const int64_t>{}, 10);
|
||||
log.Flush();
|
||||
ASSERT_EQ(data.size(), 69u);
|
||||
ASSERT_TRUE(entry.GetLastValue().has_value());
|
||||
ASSERT_EQ(entry.GetLastValue().value(), std::vector<int64_t>{});
|
||||
}
|
||||
|
||||
TEST_F(DataLogTest, DoubleArrayAppendEmpty) {
|
||||
wpi::log::DoubleArrayLogEntry entry{log, "a", 5};
|
||||
entry.Append(std::span<const double>{}, 7);
|
||||
log.Flush();
|
||||
ASSERT_EQ(data.size(), 46u);
|
||||
}
|
||||
|
||||
TEST_F(DataLogTest, DoubleArrayAppend) {
|
||||
wpi::log::DoubleArrayLogEntry entry{log, "a", 5};
|
||||
entry.Append({1.0}, 7);
|
||||
log.Flush();
|
||||
ASSERT_EQ(data.size(), 54u);
|
||||
}
|
||||
|
||||
TEST_F(DataLogTest, DoubleArrayUpdate) {
|
||||
wpi::log::DoubleArrayLogEntry entry{log, "a", 5};
|
||||
ASSERT_FALSE(entry.GetLastValue().has_value());
|
||||
entry.Update({1.0}, 7);
|
||||
log.Flush();
|
||||
ASSERT_EQ(data.size(), 54u);
|
||||
ASSERT_TRUE(entry.GetLastValue().has_value());
|
||||
ASSERT_EQ(entry.GetLastValue().value(), std::vector<double>{1.0});
|
||||
entry.Update({1.0}, 8);
|
||||
log.Flush();
|
||||
ASSERT_EQ(data.size(), 54u);
|
||||
entry.Update({2.0}, 9);
|
||||
log.Flush();
|
||||
ASSERT_EQ(data.size(), 66u);
|
||||
ASSERT_TRUE(entry.GetLastValue().has_value());
|
||||
ASSERT_EQ(entry.GetLastValue().value(), std::vector<double>{2});
|
||||
entry.Update(std::span<const double>{}, 10);
|
||||
log.Flush();
|
||||
ASSERT_EQ(data.size(), 70u);
|
||||
ASSERT_TRUE(entry.GetLastValue().has_value());
|
||||
ASSERT_EQ(entry.GetLastValue().value(), std::vector<double>{});
|
||||
}
|
||||
|
||||
TEST_F(DataLogTest, FloatArrayAppendEmpty) {
|
||||
wpi::log::FloatArrayLogEntry entry{log, "a", 5};
|
||||
entry.Append(std::span<const float>{}, 7);
|
||||
log.Flush();
|
||||
ASSERT_EQ(data.size(), 45u);
|
||||
}
|
||||
|
||||
TEST_F(DataLogTest, FloatArrayAppend) {
|
||||
wpi::log::FloatArrayLogEntry entry{log, "a", 5};
|
||||
entry.Append({1.0f}, 7);
|
||||
log.Flush();
|
||||
ASSERT_EQ(data.size(), 49u);
|
||||
}
|
||||
|
||||
TEST_F(DataLogTest, FloatArrayUpdate) {
|
||||
wpi::log::FloatArrayLogEntry entry{log, "a", 5};
|
||||
ASSERT_FALSE(entry.GetLastValue().has_value());
|
||||
entry.Update({1.0f}, 7);
|
||||
log.Flush();
|
||||
ASSERT_EQ(data.size(), 49u);
|
||||
ASSERT_TRUE(entry.GetLastValue().has_value());
|
||||
ASSERT_EQ(entry.GetLastValue().value(), std::vector<float>{1.0f});
|
||||
entry.Update({1.0f}, 8);
|
||||
log.Flush();
|
||||
ASSERT_EQ(data.size(), 49u);
|
||||
entry.Update({2.0f}, 9);
|
||||
log.Flush();
|
||||
ASSERT_EQ(data.size(), 57u);
|
||||
ASSERT_TRUE(entry.GetLastValue().has_value());
|
||||
ASSERT_EQ(entry.GetLastValue().value(), std::vector<float>{2.0f});
|
||||
entry.Update(std::span<const float>{}, 10);
|
||||
log.Flush();
|
||||
ASSERT_EQ(data.size(), 61u);
|
||||
ASSERT_TRUE(entry.GetLastValue().has_value());
|
||||
ASSERT_EQ(entry.GetLastValue().value(), std::vector<float>{});
|
||||
}
|
||||
|
||||
TEST_F(DataLogTest, StringArrayAppendEmpty) {
|
||||
wpi::log::StringArrayLogEntry entry{log, "a", 5};
|
||||
entry.Append(std::span<const std::string>{}, 7);
|
||||
entry.Append(std::span<const std::string_view>{}, 7);
|
||||
log.Flush();
|
||||
ASSERT_EQ(data.size(), 58u);
|
||||
}
|
||||
|
||||
TEST_F(DataLogTest, StringArrayAppend) {
|
||||
wpi::log::StringArrayLogEntry entry{log, "a", 5};
|
||||
entry.Append({"x"}, 7);
|
||||
log.Flush();
|
||||
ASSERT_EQ(data.size(), 55u);
|
||||
}
|
||||
|
||||
TEST_F(DataLogTest, StringArrayUpdate) {
|
||||
wpi::log::StringArrayLogEntry entry{log, "a", 5};
|
||||
ASSERT_FALSE(entry.GetLastValue().has_value());
|
||||
entry.Update({"x"}, 7);
|
||||
log.Flush();
|
||||
ASSERT_EQ(data.size(), 55u);
|
||||
ASSERT_TRUE(entry.GetLastValue().has_value());
|
||||
ASSERT_EQ(entry.GetLastValue().value(), std::vector<std::string>{"x"});
|
||||
entry.Update({"x"}, 8);
|
||||
log.Flush();
|
||||
ASSERT_EQ(data.size(), 55u);
|
||||
entry.Update({"y"}, 9);
|
||||
log.Flush();
|
||||
ASSERT_EQ(data.size(), 68u);
|
||||
ASSERT_TRUE(entry.GetLastValue().has_value());
|
||||
ASSERT_EQ(entry.GetLastValue().value(), std::vector<std::string>{"y"});
|
||||
entry.Update(std::span<const std::string_view>{}, 10);
|
||||
log.Flush();
|
||||
ASSERT_EQ(data.size(), 76u);
|
||||
ASSERT_TRUE(entry.GetLastValue().has_value());
|
||||
ASSERT_EQ(entry.GetLastValue().value(), std::vector<std::string>{});
|
||||
}
|
||||
|
||||
TEST_F(DataLogTest, StructA) {
|
||||
[[maybe_unused]]
|
||||
wpi::log::StructLogEntry<ThingA> entry0;
|
||||
wpi::log::StructLogEntry<ThingA> entry{log, "a", 5};
|
||||
entry.Append(ThingA{});
|
||||
entry.Append(ThingA{}, 7);
|
||||
}
|
||||
|
||||
TEST_F(DataLogTest, StructUpdate) {
|
||||
wpi::log::StructLogEntry<ThingA> entry{log, "a", 5};
|
||||
ASSERT_FALSE(entry.GetLastValue().has_value());
|
||||
|
||||
entry.Update(ThingA{}, 7);
|
||||
log.Flush();
|
||||
ASSERT_EQ(data.size(), 122u);
|
||||
ASSERT_TRUE(entry.GetLastValue().has_value());
|
||||
ASSERT_EQ(entry.GetLastValue().value(), ThingA{});
|
||||
|
||||
entry.Update(ThingA{}, 8);
|
||||
log.Flush();
|
||||
ASSERT_EQ(data.size(), 122u);
|
||||
|
||||
entry.Update(ThingA{.x = 1}, 9);
|
||||
log.Flush();
|
||||
ASSERT_EQ(data.size(), 127u);
|
||||
ASSERT_TRUE(entry.GetLastValue().has_value());
|
||||
ASSERT_EQ(entry.GetLastValue().value(), ThingA{.x = 1});
|
||||
}
|
||||
|
||||
TEST_F(DataLogTest, StructArrayA) {
|
||||
[[maybe_unused]]
|
||||
wpi::log::StructArrayLogEntry<ThingA> entry0;
|
||||
wpi::log::StructArrayLogEntry<ThingA> entry{log, "a", 5};
|
||||
entry.Append({{ThingA{}, ThingA{}}});
|
||||
entry.Append({{ThingA{}, ThingA{}}}, 7);
|
||||
}
|
||||
|
||||
TEST_F(DataLogTest, StructArrayUpdate) {
|
||||
wpi::log::StructArrayLogEntry<ThingA> entry{log, "a", 5};
|
||||
ASSERT_FALSE(entry.GetLastValue().has_value());
|
||||
|
||||
entry.Update({{ThingA{}, ThingA{.x = 1}}}, 7);
|
||||
log.Flush();
|
||||
ASSERT_EQ(data.size(), 125u);
|
||||
ASSERT_TRUE(entry.GetLastValue().has_value());
|
||||
ASSERT_EQ(entry.GetLastValue().value(),
|
||||
(std::vector<ThingA>{ThingA{}, ThingA{.x = 1}}));
|
||||
|
||||
entry.Update({{ThingA{}, ThingA{.x = 1}}}, 8);
|
||||
log.Flush();
|
||||
ASSERT_EQ(data.size(), 125u);
|
||||
|
||||
entry.Update({{ThingA{}, ThingA{.x = 2}}}, 9);
|
||||
log.Flush();
|
||||
ASSERT_EQ(data.size(), 131u);
|
||||
ASSERT_TRUE(entry.GetLastValue().has_value());
|
||||
ASSERT_EQ(entry.GetLastValue().value(),
|
||||
(std::vector<ThingA>{ThingA{}, ThingA{.x = 2}}));
|
||||
|
||||
entry.Update(std::span<const ThingA>{}, 10);
|
||||
log.Flush();
|
||||
ASSERT_EQ(data.size(), 135u);
|
||||
ASSERT_TRUE(entry.GetLastValue().has_value());
|
||||
ASSERT_EQ(entry.GetLastValue().value(), std::vector<ThingA>{});
|
||||
}
|
||||
|
||||
TEST_F(DataLogTest, StructFixedArrayA) {
|
||||
[[maybe_unused]]
|
||||
wpi::log::StructArrayLogEntry<std::array<ThingA, 2>> entry0;
|
||||
wpi::log::StructLogEntry<std::array<ThingA, 2>> entry{log, "a", 5};
|
||||
std::array<ThingA, 2> arr;
|
||||
entry.Append(arr);
|
||||
entry.Append(arr, 7);
|
||||
}
|
||||
|
||||
TEST_F(DataLogTest, StructB) {
|
||||
Info1 info;
|
||||
[[maybe_unused]]
|
||||
wpi::log::StructLogEntry<ThingB, Info1> entry0;
|
||||
wpi::log::StructLogEntry<ThingB, Info1> entry{log, "b", info, 5};
|
||||
entry.Append(ThingB{});
|
||||
entry.Append(ThingB{}, 7);
|
||||
}
|
||||
|
||||
TEST_F(DataLogTest, StructArrayB) {
|
||||
Info1 info;
|
||||
[[maybe_unused]]
|
||||
wpi::log::StructArrayLogEntry<ThingB, Info1> entry0;
|
||||
wpi::log::StructArrayLogEntry<ThingB, Info1> entry{log, "a", info, 5};
|
||||
entry.Append({{ThingB{}, ThingB{}}});
|
||||
entry.Append({{ThingB{}, ThingB{}}}, 7);
|
||||
}
|
||||
|
||||
TEST_F(DataLogTest, StructFixedArrayB) {
|
||||
Info1 info;
|
||||
wpi::log::StructLogEntry<std::array<ThingB, 2>, Info1> entry{log, "a", info,
|
||||
5};
|
||||
std::array<ThingB, 2> arr;
|
||||
entry.Append(arr);
|
||||
entry.Append(arr, 7);
|
||||
}
|
||||
|
||||
TEST_F(DataLogTest, StructC) {
|
||||
{
|
||||
wpi::log::StructLogEntry<ThingC> entry{log, "c", 5};
|
||||
entry.Append(ThingC{});
|
||||
entry.Append(ThingC{}, 7);
|
||||
}
|
||||
{
|
||||
Info1 info;
|
||||
wpi::log::StructLogEntry<ThingC, Info1> entry{log, "c1", info, 5};
|
||||
entry.Append(ThingC{});
|
||||
entry.Append(ThingC{}, 7);
|
||||
}
|
||||
{
|
||||
Info2 info;
|
||||
wpi::log::StructLogEntry<ThingC, Info2> entry{log, "c2", info, 5};
|
||||
entry.Append(ThingC{});
|
||||
entry.Append(ThingC{}, 7);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(DataLogTest, StructArrayC) {
|
||||
{
|
||||
wpi::log::StructArrayLogEntry<ThingC> entry{log, "c", 5};
|
||||
entry.Append({{ThingC{}, ThingC{}}});
|
||||
entry.Append({{ThingC{}, ThingC{}}}, 7);
|
||||
}
|
||||
{
|
||||
Info1 info;
|
||||
wpi::log::StructArrayLogEntry<ThingC, Info1> entry{log, "c1", info, 5};
|
||||
entry.Append({{ThingC{}, ThingC{}}});
|
||||
entry.Append({{ThingC{}, ThingC{}}}, 7);
|
||||
}
|
||||
{
|
||||
Info2 info;
|
||||
wpi::log::StructArrayLogEntry<ThingC, Info2> entry{log, "c2", info, 5};
|
||||
entry.Append({{ThingC{}, ThingC{}}});
|
||||
entry.Append({{ThingC{}, ThingC{}}}, 7);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(DataLogTest, StructFixedArrayC) {
|
||||
std::array<ThingC, 2> arr;
|
||||
{
|
||||
wpi::log::StructLogEntry<std::array<ThingC, 2>> entry{log, "c", 5};
|
||||
entry.Append(arr);
|
||||
entry.Append(arr, 7);
|
||||
}
|
||||
{
|
||||
Info1 info;
|
||||
wpi::log::StructLogEntry<std::array<ThingC, 2>, Info1> entry{log, "c1",
|
||||
info, 5};
|
||||
entry.Append(arr);
|
||||
entry.Append(arr, 7);
|
||||
}
|
||||
{
|
||||
Info2 info;
|
||||
wpi::log::StructLogEntry<std::array<ThingC, 2>, Info2> entry{log, "c2",
|
||||
info, 5};
|
||||
entry.Append(arr);
|
||||
entry.Append(arr, 7);
|
||||
}
|
||||
}
|
||||
59
datalog/src/test/native/cpp/FileLoggerTest.cpp
Normal file
59
datalog/src/test/native/cpp/FileLoggerTest.cpp
Normal file
@@ -0,0 +1,59 @@
|
||||
// Copyright (c) FIRST and other WPILib contributors.
|
||||
// Open Source Software; you can modify and/or share it under the terms of
|
||||
// the WPILib BSD license file in the root directory of this project.
|
||||
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <vector>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include "wpi/datalog/FileLogger.h"
|
||||
|
||||
TEST(FileLoggerTest, BufferSingleLine) {
|
||||
std::vector<std::string> buf;
|
||||
auto func = wpi::log::FileLogger::Buffer(
|
||||
[&buf](std::string_view line) { buf.emplace_back(line); });
|
||||
func("qwertyuiop\n");
|
||||
EXPECT_EQ("qwertyuiop", buf[0]);
|
||||
}
|
||||
|
||||
TEST(FileLoggerTest, BufferMultiLine) {
|
||||
std::vector<std::string> buf;
|
||||
auto func = wpi::log::FileLogger::Buffer(
|
||||
[&buf](std::string_view line) { buf.emplace_back(line); });
|
||||
func("line 1\nline 2\nline 3\n");
|
||||
EXPECT_EQ("line 1\nline 2\nline 3", buf[0]);
|
||||
}
|
||||
|
||||
TEST(FileLoggerTest, BufferPartials) {
|
||||
std::vector<std::string> buf;
|
||||
auto func = wpi::log::FileLogger::Buffer(
|
||||
[&buf](std::string_view line) { buf.emplace_back(line); });
|
||||
func("part 1");
|
||||
func("part 2\npart 3");
|
||||
EXPECT_EQ("part 1part 2", buf[0]);
|
||||
func("\n");
|
||||
EXPECT_EQ("part 3", buf[1]);
|
||||
}
|
||||
|
||||
TEST(FileLoggerTest, BufferMultiplePartials) {
|
||||
std::vector<std::string> buf;
|
||||
auto func = wpi::log::FileLogger::Buffer(
|
||||
[&buf](std::string_view line) { buf.emplace_back(line); });
|
||||
func("part 1");
|
||||
func("part 2");
|
||||
func("part 3");
|
||||
func("part 4\n");
|
||||
EXPECT_EQ("part 1part 2part 3part 4", buf[0]);
|
||||
}
|
||||
TEST(FileLoggerTest, BufferMultipleMultiLinePartials) {
|
||||
std::vector<std::string> buf;
|
||||
auto func = wpi::log::FileLogger::Buffer(
|
||||
[&buf](std::string_view line) { buf.emplace_back(line); });
|
||||
func("part 1");
|
||||
func("part 2\npart 3");
|
||||
func("part 4\n");
|
||||
EXPECT_EQ("part 1part 2", buf[0]);
|
||||
EXPECT_EQ("part 3part 4", buf[1]);
|
||||
}
|
||||
11
datalog/src/test/native/cpp/main.cpp
Normal file
11
datalog/src/test/native/cpp/main.cpp
Normal file
@@ -0,0 +1,11 @@
|
||||
// Copyright (c) FIRST and other WPILib contributors.
|
||||
// Open Source Software; you can modify and/or share it under the terms of
|
||||
// the WPILib BSD license file in the root directory of this project.
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
::testing::InitGoogleTest(&argc, argv);
|
||||
int ret = RUN_ALL_TESTS();
|
||||
return ret;
|
||||
}
|
||||
Reference in New Issue
Block a user