osb/source/test/net_states_test.cpp
2023-06-20 14:33:09 +10:00

1059 lines
31 KiB
C++

#include "StarNetElementSystem.hpp"
#include "gtest/gtest.h"
using namespace Star;
TEST(NetElements, DataRounding) {
NetElementFloat masterField1;
NetElementFloat masterField2;
NetElementTop<NetElementGroup> master;
master.addNetElement(&masterField1);
master.addNetElement(&masterField2);
masterField1.setFixedPointBase(0.1f);
masterField2.setFixedPointBase(0.5);
masterField1.set(2.1999f);
masterField2.set(100.04);
// Check to make sure encoded data is actually sent with the expected
// limitations to the client side.
NetElementFloat slaveField1;
NetElementFloat slaveField2;
NetElementTop<NetElementGroup> slave;
slave.addNetElement(&slaveField1);
slave.addNetElement(&slaveField2);
slaveField1.setFixedPointBase(0.1f);
slaveField2.setFixedPointBase(0.5);
auto masterUpdate1 = master.writeNetState();
slave.readNetState(masterUpdate1.first);
EXPECT_LT(fabs(slaveField1.get() - 2.2f), 0.00001f);
EXPECT_LT(fabs(slaveField2.get() - 100), 0.0000001);
// Make sure that jittering a fixed point or limited value doesn't cause
// extra deltas
masterField1.set(2.155f);
masterField1.set(2.24f);
masterField2.set(99.96);
masterField2.set(100.00);
auto masterUpdate2 = master.writeNetState(masterUpdate1.second);
EXPECT_TRUE(masterUpdate2.first.empty());
slave.readNetState(masterUpdate2.first);
masterField1.set(10.0f);
masterField2.set(50.0f);
auto masterUpdate3 = master.writeNetState(masterUpdate2.second);
EXPECT_FALSE(masterUpdate3.first.empty());
slave.readNetState(masterUpdate3.first);
EXPECT_LT(fabs(slaveField1.get() - 10.0f), 0.00001f);
EXPECT_LT(fabs(slaveField2.get() - 50.0f), 0.0000001);
}
TEST(NetElements, DirectWriteRead) {
NetElementUInt masterField1;
NetElementUInt masterField2;
NetElementUInt masterField3;
NetElementUInt masterField4;
NetElementTop<NetElementGroup> master;
master.addNetElement(&masterField1);
master.addNetElement(&masterField2);
master.addNetElement(&masterField3);
master.addNetElement(&masterField4);
masterField1.set(1);
masterField2.set(2);
masterField3.set(3);
masterField4.set(4);
NetElementUInt slaveField1;
NetElementUInt slaveField2;
NetElementUInt slaveField3;
NetElementUInt slaveField4;
NetElementTop<NetElementGroup> slave;
slave.addNetElement(&slaveField1);
slave.addNetElement(&slaveField2);
slave.addNetElement(&slaveField3);
slave.addNetElement(&slaveField4);
auto masterUpdate1 = master.writeNetState();
slave.readNetState(masterUpdate1.first);
EXPECT_EQ(slaveField1.get(), 1u);
EXPECT_EQ(slaveField2.get(), 2u);
EXPECT_EQ(slaveField3.get(), 3u);
EXPECT_EQ(slaveField4.get(), 4u);
masterField1.set(10);
masterField3.set(30);
auto masterUpdate2 = master.writeNetState(masterUpdate1.second);
slave.readNetState(masterUpdate2.first);
EXPECT_EQ(slaveField1.get(), 10u);
EXPECT_EQ(slaveField2.get(), 2u);
EXPECT_EQ(slaveField3.get(), 30u);
EXPECT_EQ(slaveField4.get(), 4u);
masterField2.set(20);
masterField4.set(40);
auto masterUpdate3 = master.writeNetState(masterUpdate2.second);
slave.readNetState(masterUpdate3.first);
EXPECT_EQ(slaveField1.get(), 10u);
EXPECT_EQ(slaveField2.get(), 20u);
EXPECT_EQ(slaveField3.get(), 30u);
EXPECT_EQ(slaveField4.get(), 40u);
}
TEST(NetElements, DeltaSize) {
NetElementInt masterField1;
NetElementUInt masterField2;
NetElementUInt masterField3;
NetElementSize masterField4;
NetElementTop<NetElementGroup> master;
master.addNetElement(&masterField1);
master.addNetElement(&masterField2);
master.addNetElement(&masterField3);
master.addNetElement(&masterField4);
NetElementInt slaveField1;
NetElementUInt slaveField2;
NetElementUInt slaveField3;
NetElementSize slaveField4;
NetElementTop<NetElementGroup> slave;
slave.addNetElement(&slaveField1);
slave.addNetElement(&slaveField2);
slave.addNetElement(&slaveField3);
slave.addNetElement(&slaveField4);
masterField1.set(10);
masterField2.set(20);
masterField3.set(30);
masterField4.set(40);
EXPECT_EQ(masterField1.get(), 10);
EXPECT_EQ(masterField2.get(), 20u);
EXPECT_EQ(masterField3.get(), 30u);
EXPECT_EQ(masterField4.get(), 40u);
auto masterUpdate1 = master.writeNetState();
// Initial state should be 5 bytes, 1 byte for header, then 4 1 byte values.
EXPECT_EQ(masterUpdate1.first.size(), 5u);
slave.readNetState(masterUpdate1.first);
EXPECT_EQ(slaveField1.get(), 10);
EXPECT_EQ(slaveField2.get(), 20u);
EXPECT_EQ(slaveField3.get(), 30u);
EXPECT_EQ(slaveField4.get(), 40u);
masterField1.set(50);
auto masterUpdate2 = master.writeNetState(masterUpdate1.second);
// Second delta should be not include any other data than the single 1 byte
// changed state, so make sure that it is 1 byte for header, 1 byte for field
// number, 1 byte for state, 1 byte for end marker.
EXPECT_EQ(masterUpdate2.first.size(), 4u);
slave.readNetState(masterUpdate2.first);
EXPECT_EQ(slaveField1.get(), 50);
}
TEST(NetElements, Forwarding) {
NetElementInt masterField1;
NetElementData<String> masterField2;
NetElementTop<NetElementGroup> master;
master.addNetElement(&masterField1);
master.addNetElement(&masterField2);
NetElementInt forwarderField1;
NetElementData<String> forwarderField2;
NetElementTop<NetElementGroup> forwarder;
forwarder.addNetElement(&forwarderField1);
forwarder.addNetElement(&forwarderField2);
NetElementInt slaveField1;
NetElementData<String> slaveField2;
NetElementTop<NetElementGroup> slave;
slave.addNetElement(&slaveField1);
slave.addNetElement(&slaveField2);
masterField1.set(413);
masterField2.set("foo");
auto masterUpdate1 = master.writeNetState();
forwarder.readNetState(masterUpdate1.first);
auto forwarderUpdate1 = forwarder.writeNetState();
slave.readNetState(forwarderUpdate1.first);
EXPECT_EQ(forwarderField1.get(), 413);
EXPECT_EQ(forwarderField2.get(), "foo");
EXPECT_EQ(slaveField1.get(), 413);
EXPECT_EQ(slaveField2.get(), "foo");
}
TEST(NetElements, StepForwarding) {
NetElementInt masterField1;
NetElementInt masterField2;
NetElementTop<NetElementGroup> master;
master.addNetElement(&masterField1);
master.addNetElement(&masterField2);
NetElementInt forwarderField1;
NetElementInt forwarderField2;
NetElementTop<NetElementGroup> forwarder;
forwarder.addNetElement(&forwarderField1);
forwarder.addNetElement(&forwarderField2);
NetElementInt slaveField1;
NetElementInt slaveField2;
NetElementTop<NetElementGroup> slave;
slave.addNetElement(&slaveField1);
slave.addNetElement(&slaveField2);
// First emulate store / load that would happen in entity initialization.
masterField1.set(10);
masterField2.set(20);
auto masterUpdate1 = master.writeNetState();
forwarder.readNetState(masterUpdate1.first);
auto forwarderUpdate1 = forwarder.writeNetState();
slave.readNetState(forwarderUpdate1.first);
EXPECT_EQ(forwarderField1.get(), 10);
EXPECT_EQ(forwarderField2.get(), 20);
EXPECT_EQ(slaveField1.get(), 10);
EXPECT_EQ(slaveField2.get(), 20);
// Then, update one field and transmit that delta[ to the forwarder.
masterField1.set(413);
auto masterUpdate2 = master.writeNetState(masterUpdate1.second);
forwarder.readNetState(masterUpdate2.first);
EXPECT_EQ(forwarderField1.get(), 413);
auto forwarderUpdate2 = forwarder.writeNetState(forwarderUpdate1.second);
slave.readNetState(forwarderUpdate2.first);
EXPECT_EQ(slaveField1.get(), 413);
EXPECT_EQ(forwarderField1.get(), 413);
EXPECT_EQ(forwarderField2.get(), 20);
EXPECT_EQ(slaveField1.get(), 413);
EXPECT_EQ(slaveField2.get(), 20);
}
TEST(NetElements, InterpolationForwarding) {
NetElementInt masterField1;
NetElementFloat masterField2;
NetElementData<String> masterField3;
NetElementTop<NetElementGroup> master;
master.addNetElement(&masterField1);
master.addNetElement(&masterField2);
master.addNetElement(&masterField3);
NetElementInt forwarderField1;
NetElementFloat forwarderField2;
NetElementData<String> forwarderField3;
NetElementTop<NetElementGroup> forwarder;
forwarder.addNetElement(&forwarderField1);
forwarder.addNetElement(&forwarderField2);
forwarder.addNetElement(&forwarderField3);
NetElementInt slaveField1;
NetElementFloat slaveField2;
NetElementData<String> slaveField3;
NetElementTop<NetElementGroup> slave;
slave.addNetElement(&slaveField1);
slave.addNetElement(&slaveField2);
slave.addNetElement(&slaveField3);
forwarder.enableNetInterpolation();
slave.enableNetInterpolation();
masterField1.set(10);
masterField2.set(10.0f);
masterField3.set("10");
auto masterUpdate1 = master.writeNetState();
forwarder.readNetState(masterUpdate1.first);
auto forwarderUpdate1 = forwarder.writeNetState();
slave.readNetState(forwarderUpdate1.first);
EXPECT_EQ(forwarderField1.get(), 10);
EXPECT_EQ(forwarderField2.get(), 10.0f);
EXPECT_EQ(forwarderField3.get(), "10");
EXPECT_EQ(slaveField1.get(), 10);
EXPECT_EQ(slaveField2.get(), 10.0f);
EXPECT_EQ(slaveField3.get(), "10");
masterField1.set(20);
masterField2.set(20.0f);
masterField3.set("20");
auto masterUpdate2 = master.writeNetState(masterUpdate1.second);
forwarder.readNetState(masterUpdate2.first, 1.0f);
// Forwarder should not be updated yet, still 1.0f interpolationTime behind
EXPECT_EQ(forwarderField1.get(), 10);
EXPECT_EQ(forwarderField2.get(), 10.0f);
EXPECT_EQ(forwarderField3.get(), "10");
// But the forwarder should STILL forward the absolute latest data to the
// slave
auto forwarderUpdate2 = forwarder.writeNetState(forwarderUpdate1.second);
slave.readNetState(forwarderUpdate2.first, 1.0f);
// Slave should not be updated yet, still 1.0f interpolationTime behind
EXPECT_EQ(slaveField1.get(), 10);
EXPECT_EQ(slaveField2.get(), 10.0f);
EXPECT_EQ(slaveField3.get(), "10");
// After ticking forward interpolation, both the forwarder and the slave
// should both pick up the new values.
forwarder.tickNetInterpolation(1.0f);
EXPECT_EQ(forwarderField1.get(), 20);
EXPECT_EQ(forwarderField2.get(), 20.0f);
EXPECT_EQ(forwarderField3.get(), "20");
slave.tickNetInterpolation(1.0f);
EXPECT_EQ(slaveField1.get(), 20);
EXPECT_EQ(slaveField2.get(), 20.0f);
EXPECT_EQ(slaveField3.get(), "20");
}
TEST(NetElements, MasterSetGet) {
// Make sure that Master mode sets, gets, and pullEventOccurred work
// properly.
NetElementInt masterField1;
NetElementData<String> masterField2;
NetElementEvent masterField3;
NetElementTop<NetElementGroup> master;
master.addNetElement(&masterField1);
master.addNetElement(&masterField2);
master.addNetElement(&masterField3);
EXPECT_EQ(masterField3.pullOccurrences(), 0u);
masterField1.set(10);
masterField2.set("foo");
EXPECT_EQ(masterField1.get(), 10);
EXPECT_EQ(masterField2.get(), "foo");
masterField3.trigger();
masterField3.trigger();
EXPECT_EQ(masterField3.pullOccurrences(), 2u);
EXPECT_EQ(masterField3.pullOccurrences(), 0u);
}
TEST(NetElements, IsolatedSetGet) {
// Make sure fields work without being connected
NetElementInt masterField1;
NetElementData<String> masterField2;
NetElementEvent masterField3;
EXPECT_EQ(masterField2.pullUpdated(), false);
EXPECT_EQ(masterField3.pullOccurrences(), 0u);
masterField1.set(10);
masterField2.set("foo");
EXPECT_EQ(masterField2.pullUpdated(), true);
EXPECT_EQ(masterField2.pullUpdated(), false);
EXPECT_EQ(masterField1.get(), 10);
EXPECT_EQ(masterField2.get(), "foo");
masterField3.trigger();
masterField3.trigger();
EXPECT_EQ(masterField3.pullOccurrences(), 2u);
EXPECT_EQ(masterField3.pullOccurrences(), 0u);
masterField1.set(20);
masterField2.set("bar");
masterField3.trigger();
masterField3.trigger();
EXPECT_EQ(masterField3.pullOccurrences(), 2u);
}
TEST(NetElements, EventTest) {
NetElementData<String> masterField1;
NetElementEvent masterField2;
NetElementTop<NetElementGroup> master;
master.addNetElement(&masterField1);
master.addNetElement(&masterField2);
NetElementData<String> slaveField1;
NetElementEvent slaveField2;
NetElementTop<NetElementGroup> slave;
slave.addNetElement(&slaveField1);
slave.addNetElement(&slaveField2);
// Events should always start with occurred false.
EXPECT_EQ(slaveField1.pullUpdated(), false);
EXPECT_EQ(slaveField2.pullOccurrences(), 0u);
masterField1.set("foo");
masterField2.trigger();
EXPECT_TRUE(masterField1.pullUpdated());
EXPECT_FALSE(masterField1.pullUpdated());
auto masterUpdate1 = master.writeNetState();
slave.readNetState(masterUpdate1.first);
EXPECT_TRUE(slaveField1.pullUpdated());
EXPECT_FALSE(slaveField1.pullUpdated());
EXPECT_EQ(slaveField2.pullOccurrences(), 1u);
EXPECT_EQ(slaveField2.pullOccurrences(), 0u);
// Delta should be empty, nothing happened on step 1.
auto masterUpdate2 = master.writeNetState(masterUpdate1.second);
EXPECT_TRUE(masterUpdate2.first.empty());
slave.readNetState(masterUpdate2.first);
EXPECT_EQ(slaveField2.pullOccurrences(), 0u);
masterField2.trigger();
auto masterUpdate3 = master.writeNetState(masterUpdate2.second);
EXPECT_FALSE(masterUpdate3.first.empty());
slave.readNetState(masterUpdate3.first);
EXPECT_EQ(slaveField2.pullOccurrences(), 1u);
EXPECT_EQ(slaveField2.pullOccurrences(), 0u);
}
TEST(NetElements, FieldUpdated) {
NetElementData<String> masterField1;
NetElementInt masterField2;
NetElementEvent masterField3;
NetElementEvent masterField4;
NetElementTop<NetElementGroup> master;
master.addNetElement(&masterField1);
master.addNetElement(&masterField2);
master.addNetElement(&masterField3);
master.addNetElement(&masterField4);
NetElementData<String> slaveField1;
NetElementInt slaveField2;
NetElementEvent slaveField3;
NetElementEvent slaveField4;
NetElementTop<NetElementGroup> slave;
slave.addNetElement(&slaveField1);
slave.addNetElement(&slaveField2);
slave.addNetElement(&slaveField3);
slave.addNetElement(&slaveField4);
slaveField4.setIgnoreOccurrencesOnNetLoad(true);
masterField1.set("foo");
masterField3.trigger();
masterField4.trigger();
auto masterUpdate1 = master.writeNetState();
slave.readNetState(masterUpdate1.first);
EXPECT_EQ(slaveField1.pullUpdated(), true);
EXPECT_EQ(slaveField1.get(), "foo");
EXPECT_EQ(slaveField1.pullUpdated(), false);
EXPECT_EQ(masterField3.pullOccurrences(), 1u);
EXPECT_EQ(slaveField3.pullOccurrences(), 1u);
// Ignore occurrences on full load should stop slaveField4 from getting any
// occurrences
EXPECT_EQ(masterField4.pullOccurrences(), 1u);
EXPECT_EQ(slaveField4.pullOccurrences(), 0u);
masterField1.set("baz");
auto masterUpdate2 = master.writeNetState(masterUpdate1.second);
EXPECT_FALSE(masterUpdate2.first.empty());
slave.readNetState(masterUpdate2.first);
EXPECT_EQ(slaveField1.get(), "baz");
EXPECT_EQ(slaveField1.pullUpdated(), true);
masterField1.set("bar");
auto masterUpdate3 = master.writeNetState(masterUpdate2.second);
EXPECT_FALSE(masterUpdate3.first.empty());
slave.readNetState(masterUpdate3.first);
EXPECT_EQ(slaveField1.get(), "bar");
EXPECT_EQ(slaveField1.pullUpdated(), true);
masterField1.push("bar");
auto masterUpdate4 = master.writeNetState(masterUpdate3.second);
EXPECT_FALSE(masterUpdate4.first.empty());
slave.readNetState(masterUpdate4.first);
EXPECT_EQ(slaveField1.get(), "bar");
EXPECT_EQ(slaveField1.pullUpdated(), true);
auto masterUpdate5 = master.writeNetState(masterUpdate4.second);
EXPECT_TRUE(masterUpdate5.first.empty());
slave.readNetState(masterUpdate5.first);
EXPECT_EQ(slaveField1.get(), "bar");
EXPECT_EQ(slaveField1.pullUpdated(), false);
masterField3.trigger();
masterField3.trigger();
auto masterUpdate6 = master.writeNetState(masterUpdate5.second);
EXPECT_FALSE(masterUpdate6.first.empty());
slave.readNetState(masterUpdate6.first);
slaveField3.ignoreOccurrences();
// occurrence should not come through after "ignoreOccurrences"
EXPECT_EQ(slaveField3.pullOccurrences(), 0u);
EXPECT_EQ(masterField3.pullOccurrences(), 2u);
masterField3.trigger();
masterField3.trigger();
masterField3.ignoreOccurrences();
auto masterUpdate7 = master.writeNetState(masterUpdate6.second);
EXPECT_FALSE(masterUpdate7.first.empty());
slave.readNetState(masterUpdate7.first);
// ignoreOccurrences is LOCAL only, so events should still go through to the
// slave
EXPECT_EQ(masterField3.pullOccurrences(), 0u);
EXPECT_EQ(slaveField3.pullOccurrences(), 2u);
EXPECT_EQ(slaveField3.pullOccurrences(), 0u);
}
TEST(NetElements, Interpolation) {
NetElementFloat masterField1;
NetElementData<String> masterField2;
NetElementTop<NetElementGroup> master;
master.addNetElement(&masterField1);
master.addNetElement(&masterField2);
masterField1.set(1.0f);
masterField2.set("yes");
NetElementFloat slaveField1;
NetElementData<String> slaveField2;
NetElementTop<NetElementGroup> slave;
slave.addNetElement(&slaveField1);
slave.addNetElement(&slaveField2);
slaveField1.setInterpolator(lerp<double, double>);
slave.enableNetInterpolation();
auto masterUpdate1 = master.writeNetState();
slave.readNetState(masterUpdate1.first);
masterField1.set(2.0f);
masterField2.set("no");
auto masterUpdate2 = master.writeNetState(masterUpdate1.second);
slave.readNetState(masterUpdate2.first, 2.0);
masterField1.set(3.0f);
masterField2.set("yes");
auto masterUpdate3 = master.writeNetState(masterUpdate2.second);
slave.readNetState(masterUpdate3.first, 4.0);
masterField1.set(4.0f);
masterField2.set("no");
auto masterUpdate4 = master.writeNetState(masterUpdate3.second);
slave.readNetState(masterUpdate4.first, 6.0);
EXPECT_TRUE(fabs(slaveField1.get() - 1.0) < 0.001);
EXPECT_EQ(slaveField2.get(), "yes");
EXPECT_EQ(slaveField2.pullUpdated(), true);
slave.tickNetInterpolation(1.0f);
EXPECT_TRUE(fabs(slaveField1.get() - 1.5) < 0.001);
EXPECT_EQ(slaveField2.get(), "yes");
EXPECT_EQ(slaveField2.pullUpdated(), false);
slave.tickNetInterpolation(1.0f);
EXPECT_TRUE(fabs(slaveField1.get() - 2.0) < 0.001);
EXPECT_EQ(slaveField2.get(), "no");
EXPECT_EQ(slaveField2.pullUpdated(), true);
slave.tickNetInterpolation(1.0f);
EXPECT_TRUE(fabs(slaveField1.get() - 2.5) < 0.001);
EXPECT_EQ(slaveField2.get(), "no");
EXPECT_EQ(slaveField2.pullUpdated(), false);
slave.tickNetInterpolation(1.0f);
EXPECT_TRUE(fabs(slaveField1.get() - 3.0) < 0.001);
EXPECT_EQ(slaveField2.get(), "yes");
EXPECT_EQ(slaveField2.pullUpdated(), true);
slave.tickNetInterpolation(1.0f);
EXPECT_TRUE(fabs(slaveField1.get() - 3.5) < 0.001);
EXPECT_EQ(slaveField2.get(), "yes");
EXPECT_EQ(slaveField2.pullUpdated(), false);
slave.tickNetInterpolation(1.0f);
EXPECT_TRUE(fabs(slaveField1.get() - 4.0) < 0.001);
EXPECT_EQ(slaveField2.pullUpdated(), true);
EXPECT_EQ(slaveField2.get(), "no");
}
enum class TestEnum {
Value1,
Value2,
Value3
};
TEST(NetElements, AllTypes) {
NetElementInt masterField1;
NetElementUInt masterField2;
NetElementSize masterField3;
NetElementFloat masterField4;
NetElementDouble masterField5;
NetElementFloat masterField6;
masterField6.setFixedPointBase(0.01f);
NetElementDouble masterField7;
masterField7.setFixedPointBase(0.01);
NetElementBool masterField8;
NetElementEnum<TestEnum> masterField9;
NetElementEvent masterField10;
NetElementData<Vec2F> masterField11;
NetElementTop<NetElementGroup> master;
master.addNetElement(&masterField1);
master.addNetElement(&masterField2);
master.addNetElement(&masterField3);
master.addNetElement(&masterField4);
master.addNetElement(&masterField5);
master.addNetElement(&masterField6);
master.addNetElement(&masterField7);
master.addNetElement(&masterField8);
master.addNetElement(&masterField9);
master.addNetElement(&masterField10);
master.addNetElement(&masterField11);
masterField1.set(567);
masterField2.set(17000);
masterField3.set(22222);
masterField4.set(1.55f);
masterField5.set(1.12345678910111213);
masterField6.set(2000.62f);
masterField7.set(2000.62);
masterField8.set(true);
masterField9.set(TestEnum::Value2);
masterField10.trigger();
masterField11.set(Vec2F(2.0f, 2.0f));
EXPECT_EQ(masterField1.get(), 567);
EXPECT_EQ(masterField2.get(), 17000u);
EXPECT_EQ(masterField3.get(), 22222u);
EXPECT_FLOAT_EQ(masterField4.get(), 1.55f);
EXPECT_FLOAT_EQ(masterField5.get(), 1.12345678910111213);
EXPECT_FLOAT_EQ(masterField6.get(), 2000.62f);
EXPECT_FLOAT_EQ(masterField7.get(), 2000.62);
EXPECT_EQ(masterField8.get(), true);
EXPECT_EQ(masterField9.get(), TestEnum::Value2);
EXPECT_TRUE(masterField10.pullOccurred());
EXPECT_TRUE(masterField11.get() == Vec2F(2.0f, 2.0f));
NetElementInt slaveField1;
NetElementUInt slaveField2;
NetElementSize slaveField3;
NetElementFloat slaveField4;
NetElementDouble slaveField5;
NetElementFloat slaveField6;
slaveField6.setFixedPointBase(0.01f);
NetElementDouble slaveField7;
slaveField7.setFixedPointBase(0.01);
NetElementBool slaveField8;
NetElementEnum<TestEnum> slaveField9;
NetElementEvent slaveField10;
NetElementData<Vec2F> slaveField11;
NetElementTop<NetElementGroup> slave;
slave.addNetElement(&slaveField1);
slave.addNetElement(&slaveField2);
slave.addNetElement(&slaveField3);
slave.addNetElement(&slaveField4);
slave.addNetElement(&slaveField5);
slave.addNetElement(&slaveField6);
slave.addNetElement(&slaveField7);
slave.addNetElement(&slaveField8);
slave.addNetElement(&slaveField9);
slave.addNetElement(&slaveField10);
slave.addNetElement(&slaveField11);
slave.readNetState(master.writeNetState().first);
EXPECT_EQ(slaveField1.get(), 567);
EXPECT_EQ(slaveField2.get(), 17000u);
EXPECT_EQ(slaveField3.get(), 22222u);
EXPECT_FLOAT_EQ(slaveField4.get(), 1.55f);
EXPECT_FLOAT_EQ(slaveField5.get(), 1.12345678910111213);
EXPECT_FLOAT_EQ(slaveField6.get(), 2000.62f);
EXPECT_FLOAT_EQ(slaveField7.get(), 2000.62);
EXPECT_EQ(slaveField8.get(), true);
EXPECT_EQ(slaveField9.get(), TestEnum::Value2);
EXPECT_TRUE(slaveField10.pullOccurred());
EXPECT_TRUE(slaveField11.get() == Vec2F(2.0f, 2.0f));
}
TEST(NetElements, NetElementDynamicGroup) {
class TestElement : public NetElementGroup {
public:
TestElement(int value = 0) {
addNetElement(&dataState);
dataState.set(value);
}
void setData(int value) {
dataState.set(value);
}
int getData() const {
return dataState.get();
}
private:
NetElementInt dataState;
};
NetElementTop<NetElementDynamicGroup<TestElement>> masterGroup;
NetElementTop<NetElementDynamicGroup<TestElement>> slaveGroup;
uint64_t lastSlaveUpdateVersion = 0;
auto sendSlaveUpdate = [&]() {
auto p = masterGroup.writeNetState(lastSlaveUpdateVersion);
lastSlaveUpdateVersion = p.second;
slaveGroup.readNetState(p.first);
};
auto objId1 = masterGroup.addNetElement(make_shared<TestElement>(1000));
auto objId2 = masterGroup.addNetElement(make_shared<TestElement>(2000));
EXPECT_EQ(masterGroup.netElementIds().size(), 2u);
EXPECT_EQ(masterGroup.getNetElement(objId1)->getData(), 1000);
EXPECT_EQ(masterGroup.getNetElement(objId2)->getData(), 2000);
sendSlaveUpdate();
EXPECT_EQ(slaveGroup.netElementIds().size(), 2u);
EXPECT_EQ(slaveGroup.getNetElement(objId1)->getData(), 1000);
EXPECT_EQ(slaveGroup.getNetElement(objId2)->getData(), 2000);
masterGroup.getNetElement(objId1)->setData(1001);
masterGroup.getNetElement(objId2)->setData(2001);
sendSlaveUpdate();
EXPECT_EQ(slaveGroup.getNetElement(objId1)->getData(), 1001);
EXPECT_EQ(slaveGroup.getNetElement(objId2)->getData(), 2001);
masterGroup.getNetElement(objId1)->setData(1002);
masterGroup.getNetElement(objId2)->setData(2002);
sendSlaveUpdate();
EXPECT_EQ(masterGroup.getNetElement(objId1)->getData(), 1002);
EXPECT_EQ(masterGroup.getNetElement(objId2)->getData(), 2002);
EXPECT_EQ(slaveGroup.getNetElement(objId1)->getData(), 1002);
EXPECT_EQ(slaveGroup.getNetElement(objId2)->getData(), 2002);
auto objId3 = masterGroup.addNetElement(make_shared<TestElement>(3001));
sendSlaveUpdate();
EXPECT_EQ(slaveGroup.netElementIds().size(), 3u);
EXPECT_EQ(slaveGroup.getNetElement(objId3)->getData(), 3001);
// Delta must be greater than MaxChangeDataSteps
auto objId4 = masterGroup.addNetElement(make_shared<TestElement>(4001));
masterGroup.getNetElement(objId3)->setData(3002);
masterGroup.getNetElement(objId4)->setData(4002);
sendSlaveUpdate();
EXPECT_EQ(slaveGroup.netElementIds().size(), 4u);
EXPECT_EQ(slaveGroup.getNetElement(objId1)->getData(), 1002);
EXPECT_EQ(slaveGroup.getNetElement(objId2)->getData(), 2002);
EXPECT_EQ(slaveGroup.getNetElement(objId3)->getData(), 3002);
EXPECT_EQ(slaveGroup.getNetElement(objId4)->getData(), 4002);
NetElementTop<NetElementDynamicGroup<TestElement>> forwardedSlaveGroup;
uint64_t lastForwardedSlaveUpdateVersion = 0;
auto sendForwardedSlaveUpdate = [&]() {
auto p = slaveGroup.writeNetState(lastForwardedSlaveUpdateVersion);
lastForwardedSlaveUpdateVersion = p.second;
forwardedSlaveGroup.readNetState(p.first);
};
sendForwardedSlaveUpdate();
EXPECT_EQ(forwardedSlaveGroup.netElementIds().size(), 4u);
EXPECT_EQ(forwardedSlaveGroup.getNetElement(objId1)->getData(), 1002);
EXPECT_EQ(forwardedSlaveGroup.getNetElement(objId2)->getData(), 2002);
EXPECT_EQ(forwardedSlaveGroup.getNetElement(objId3)->getData(), 3002);
EXPECT_EQ(forwardedSlaveGroup.getNetElement(objId4)->getData(), 4002);
masterGroup.removeNetElement(objId1);
masterGroup.removeNetElement(objId3);
masterGroup.getNetElement(objId2)->setData(2003);
masterGroup.getNetElement(objId4)->setData(4003);
sendSlaveUpdate();
sendForwardedSlaveUpdate();
auto obj5 = masterGroup.addNetElement(make_shared<TestElement>(5001));
masterGroup.removeNetElement(obj5);
sendSlaveUpdate();
sendForwardedSlaveUpdate();
EXPECT_EQ(slaveGroup.netElementIds().size(), 2u);
EXPECT_EQ(slaveGroup.getNetElement(objId2)->getData(), 2003);
EXPECT_EQ(slaveGroup.getNetElement(objId4)->getData(), 4003);
EXPECT_EQ(forwardedSlaveGroup.netElementIds().size(), 2u);
EXPECT_EQ(forwardedSlaveGroup.getNetElement(objId2)->getData(), 2003);
EXPECT_EQ(forwardedSlaveGroup.getNetElement(objId4)->getData(), 4003);
}
TEST(NetElements, NetElementMap) {
NetElementTop<NetElementMap<String, String>> masterMap;
NetElementTop<NetElementMap<String, String>> slaveMap;
uint64_t lastUpdateVersion = 0;
auto sendUpdate = [&]() {
DataStreamBuffer ds;
auto p = masterMap.writeNetState(lastUpdateVersion);
slaveMap.readNetState(p.first);
lastUpdateVersion = p.second;
return !p.first.empty();
};
masterMap.add("foo", "bar");
masterMap.add("baz", "bof");
EXPECT_EQ(masterMap.size(), 2u);
sendUpdate();
EXPECT_EQ(slaveMap.size(), 2u);
EXPECT_EQ(slaveMap.get("foo"), "bar");
EXPECT_EQ(slaveMap.get("baz"), "bof");
masterMap.add("bif", "fob");
masterMap.remove("foo");
sendUpdate();
EXPECT_EQ(slaveMap.size(), 2u);
EXPECT_EQ(slaveMap.get("bif"), "fob");
masterMap.clear();
masterMap.set("fib", "fab");
sendUpdate();
EXPECT_EQ(slaveMap.size(), 1u);
EXPECT_EQ(slaveMap.get("fib"), "fab");
masterMap.set("fib", "fab");
EXPECT_FALSE(sendUpdate());
masterMap.reset({{"a", "b"}, {"c", "d"}, {"e", "f"}});
sendUpdate();
EXPECT_EQ(slaveMap.size(), 3u);
EXPECT_EQ(slaveMap.get("a"), "b");
EXPECT_EQ(slaveMap.get("c"), "d");
EXPECT_EQ(slaveMap.get("e"), "f");
}
TEST(NetElements, NetElementMapInterpolated) {
typedef NetElementTop<NetElementMap<String, String>> TestMap;
TestMap masterMap;
TestMap forwarderMap;
uint64_t lastForwarderUpdateVersion = 0;
auto sendForwarderUpdate = [&]() {
auto p = masterMap.writeNetState(lastForwarderUpdateVersion);
lastForwarderUpdateVersion = p.second;
forwarderMap.readNetState(p.first);
return !p.first.empty();
};
TestMap slaveMap;
uint64_t lastSlaveUpdateVersion = 0;
auto sendSlaveUpdate = [&](float interpolationTime) {
auto p = forwarderMap.writeNetState(lastSlaveUpdateVersion);
lastSlaveUpdateVersion = p.second;
slaveMap.readNetState(p.first, interpolationTime);
return !p.first.empty();
};
slaveMap.enableNetInterpolation();
masterMap.add("foo", "bar");
masterMap.add("baz", "bof");
EXPECT_EQ(masterMap.size(), 2u);
sendForwarderUpdate();
sendSlaveUpdate(0.0f);
EXPECT_EQ(slaveMap.size(), 2u);
EXPECT_EQ(slaveMap.get("foo"), "bar");
EXPECT_EQ(slaveMap.get("baz"), "bof");
masterMap.add("bif", "fob");
masterMap.add("qux", "qux");
masterMap.remove("foo");
sendForwarderUpdate();
sendSlaveUpdate(1.0f);
EXPECT_EQ(slaveMap.size(), 2u);
EXPECT_EQ(slaveMap.get("foo"), "bar");
EXPECT_EQ(slaveMap.get("baz"), "bof");
slaveMap.tickNetInterpolation(1.0f);
EXPECT_EQ(slaveMap.size(), 3u);
EXPECT_EQ(slaveMap.get("baz"), "bof");
EXPECT_EQ(slaveMap.get("bif"), "fob");
EXPECT_EQ(slaveMap.get("qux"), "qux");
masterMap.clear();
masterMap.set("fib", "fab");
sendForwarderUpdate();
sendSlaveUpdate(1.0f);
EXPECT_EQ(slaveMap.size(), 3u);
slaveMap.tickNetInterpolation(1.0f);
EXPECT_EQ(forwarderMap.size(), 1u);
EXPECT_EQ(slaveMap.size(), 1u);
EXPECT_EQ(slaveMap.get("fib"), "fab");
masterMap.set("fob", "fub");
sendForwarderUpdate();
sendSlaveUpdate(1.0f);
EXPECT_EQ(slaveMap.size(), 1u);
slaveMap.disableNetInterpolation();
EXPECT_EQ(slaveMap.size(), 2u);
EXPECT_EQ(slaveMap.get("fib"), "fab");
EXPECT_EQ(slaveMap.get("fob"), "fub");
}
TEST(NetElements, NetElementSignal) {
NetElementSignal<int> masterSignal1;
NetElementSignal<int> masterSignal2;
NetElementTopGroup masterGroup;
masterGroup.addNetElement(&masterSignal1);
masterGroup.addNetElement(&masterSignal2);
NetElementSignal<int> slaveSignal1;
NetElementSignal<int> slaveSignal2;
NetElementTopGroup slaveGroup;
slaveGroup.addNetElement(&slaveSignal1);
slaveGroup.addNetElement(&slaveSignal2);
// No signals are supposed to be sent for the initial write
auto masterUpdate1 = masterGroup.writeNetState();
slaveGroup.readNetState(masterUpdate1.first);
masterSignal1.send(101);
masterSignal2.send(201);
EXPECT_EQ(masterSignal1.receive(), List<int>({101}));
EXPECT_EQ(masterSignal2.receive(), List<int>({201}));
EXPECT_EQ(masterSignal1.receive(), List<int>({}));
EXPECT_EQ(masterSignal2.receive(), List<int>({}));
auto masterUpdate2 = masterGroup.writeNetState(masterUpdate1.second);
slaveGroup.readNetState(masterUpdate2.first);
EXPECT_EQ(slaveSignal1.receive(), List<int>({101}));
EXPECT_EQ(slaveSignal2.receive(), List<int>({201}));
EXPECT_EQ(slaveSignal1.receive(), List<int>({}));
EXPECT_EQ(slaveSignal2.receive(), List<int>({}));
masterSignal1.send(102);
masterSignal2.send(202);
slaveGroup.enableNetInterpolation();
auto masterUpdate3 = masterGroup.writeNetState(masterUpdate2.second);
slaveGroup.readNetState(masterUpdate3.first, 1.0f);
EXPECT_EQ(slaveSignal1.receive(), List<int>({}));
EXPECT_EQ(slaveSignal2.receive(), List<int>({}));
slaveGroup.tickNetInterpolation(1.0f);
EXPECT_EQ(slaveSignal1.receive(), List<int>({102}));
EXPECT_EQ(slaveSignal2.receive(), List<int>({202}));
EXPECT_EQ(slaveSignal1.receive(), List<int>({}));
EXPECT_EQ(slaveSignal2.receive(), List<int>({}));
}