Commit cb124d4c authored by pfandzelter's avatar pfandzelter
Browse files

Merge branch 'nj/refactor3NodeTest' into 'master'

Refactor 3NodeTest into test suites

See merge request !121
parents 427496dc e9681739
Pipeline #10497 passed with stages
in 16 minutes and 32 seconds
package main
type AuthenticationSuite struct {
c *Config
}
func (t *AuthenticationSuite) RunTests() {
// test RBAC and authentication
logNodeAction(t.c.nodeA, "create keygroup \"rbactest\"")
t.c.nodeA.CreateKeygroup("rbactest", true, 0, false)
logNodeAction(t.c.nodeA, "put item into keygroup \"rbactest\"")
t.c.nodeA.PutItem("rbactest", "item1", "value1", false)
logNodeAction(t.c.nodeA, "add little client as read only to rbac test")
t.c.nodeA.AddUser("littleclient", "rbactest", "ReadKeygroup", false)
logNodeAction(t.c.nodeA, "try to read with little client -> should work")
if val := t.c.littleClient.GetItem("rbactest", "item1", false); val != "value1" {
logNodeFailure(t.c.nodeA, "value1", val)
}
logNodeAction(t.c.nodeA, "try to write with little client -> should not work")
t.c.littleClient.PutItem("rbactest", "item1", "value2", true)
logNodeAction(t.c.nodeA, "add role configure replica to little client -> should work")
t.c.nodeA.AddUser("littleclient", "rbactest", "ConfigureReplica", false)
logNodeAction(t.c.nodeA, "add replica nodeB to keygroup with little client -> should work")
t.c.littleClient.AddKeygroupReplica("rbactest", t.c.nodeBpeeringID, 0, false)
logNodeAction(t.c.nodeB, "remove permission to read from keygroup -> should work")
t.c.nodeB.RemoveUser("littleclient", "rbactest", "ReadKeygroup", false)
logNodeAction(t.c.nodeA, "try to read from keygroup with little client -> should not work")
if val := t.c.littleClient.GetItem("rbactest", "item1", true); val != "" {
logNodeFailure(t.c.nodeA, "", val)
}
}
func NewAuthenticationSuite(c *Config) *AuthenticationSuite {
return &AuthenticationSuite{
c: c,
}
}
package main
import (
"time"
)
type ExpirySuite struct {
c *Config
}
func (t *ExpirySuite) RunTests() {
// test expiring data items
logNodeAction(t.c.nodeC, "Create normal keygroup on nodeC without expiry")
t.c.nodeC.CreateKeygroup("expirytest", true, 0, false)
logNodeAction(t.c.nodeC, "Add nodeA as replica with expiry of 5s")
t.c.nodeC.AddKeygroupReplica("expirytest", t.c.nodeApeeringID, 5, false)
logNodeAction(t.c.nodeC, "Update something on nodeC")
t.c.nodeC.PutItem("expirytest", "test", "test", false)
logNodeAction(t.c.nodeA, "Test whether nodeA has received the update. Wait 5s and check that it is not there anymore")
t.c.nodeA.GetItem("expirytest", "test", false)
time.Sleep(5 * time.Second)
t.c.nodeA.GetItem("expirytest", "test", true)
logNodeAction(t.c.nodeC, "....the item should still exist with nodeC")
t.c.nodeC.GetItem("expirytest", "test", false)
}
func NewExpirySuite(c *Config) *ExpirySuite {
return &ExpirySuite{
c: c,
}
}
package main
type ImmutableSuite struct {
c *Config
}
func (t *ImmutableSuite) RunTests() {
// testing immutable keygroups
logNodeAction(t.c.nodeB, "Testing immutable keygroups by creating a new immutable keygroup on nodeB")
t.c.nodeB.CreateKeygroup("log", false, 0, false)
logNodeAction(t.c.nodeB, "Creating an item in this keygroup")
res := t.c.nodeB.AppendItem("log", "value1", false)
if res != "0" {
logNodeFailure(t.c.nodeB, "0", res)
}
logNodeAction(t.c.nodeB, "Updating an item in this keygroup")
t.c.nodeB.PutItem("log", res, "value-2", true)
logNodeAction(t.c.nodeB, "Getting updated item from immutable keygroup")
respB := t.c.nodeB.GetItem("log", res, false)
if respB != "value1" {
logNodeFailure(t.c.nodeB, "resp is value1", respB)
}
logNodeAction(t.c.nodeB, "Deleting an item in immutable keygroup")
t.c.nodeB.DeleteItem("log", "testitem", true)
logNodeAction(t.c.nodeB, "Adding nodeC as replica to immutable keygroup")
t.c.nodeB.AddKeygroupReplica("log", t.c.nodeCpeeringID, 0, false)
logNodeAction(t.c.nodeC, "Updating immutable item on other nodeC")
t.c.nodeC.PutItem("log", "testitem", "value-3", true)
// TODO is this the right place???
logNodeAction(t.c.nodeC, "Appending another item to readonly log.")
res = t.c.nodeC.AppendItem("log", "value-2", false)
if res != "1" {
logNodeFailure(t.c.nodeB, "1", res)
}
}
func NewImmutableSuite(c *Config) *ImmutableSuite {
return &ImmutableSuite{
c: c,
}
}
......@@ -2,12 +2,10 @@ package main
import (
"bufio"
"encoding/json"
"flag"
"fmt"
"net/http"
"os"
"strconv"
"strings"
"time"
"git.tu-berlin.de/mcc-fred/fred/tests/3NodeTest/pkg/grpcclient"
......@@ -57,6 +55,8 @@ func main() {
littleCertFile := *flag.String("little-cert-file", "/cert/littleclient.crt", "Certificate to talk to FReD as \"littleclient\"")
littleKeyFile := *flag.String("little-key-file", "/cert/littleclient.key", "Keyfile to talk to FReD as \"littleclient\"")
testRange := *flag.String("test-range", "-", "Give tests to execute as a dash-separated range. Omitted start or end become the lowest or highest possible index, respectively. Default: All tests (\"-\"). Examples: 2-7, 1-, -6, -")
flag.Parse()
port, _ := strconv.Atoi(nodeAhttpPort)
......@@ -65,333 +65,85 @@ func main() {
nodeB := grpcclient.NewNode(nodeBhost, port, certFile, keyFile)
port, _ = strconv.Atoi(nodeChttpPort)
nodeC := grpcclient.NewNode(nodeChost, port, certFile, keyFile)
port, _ = strconv.Atoi(nodeAhttpPort)
littleClient := grpcclient.NewNode(nodeAhost, port, littleCertFile, littleKeyFile)
time.Sleep(15 * time.Second)
// Test Keygroups
logNodeAction(nodeA, "Creating keygroup testing")
nodeA.CreateKeygroup("testing", true, 0, false)
logNodeAction(nodeA, "Deleting keygroup testing")
nodeA.DeleteKeygroup("testing", false)
logNodeAction(nodeA, "Deleting nonexistent keygroup")
nodeA.DeleteKeygroup("trololololo", true)
logNodeAction(nodeA, "Creating Keygroup KG1")
nodeA.CreateKeygroup("KG1", true, 0, false)
// Test Get/Put of a single node
logNodeAction(nodeA, "Putting KG1Item/KG1Value into KG1")
nodeA.PutItem("KG1", "KG1Item", "KG1Value", false)
logNodeAction(nodeA, "Getting the value in KG1")
resp := nodeA.GetItem("KG1", "KG1Item", false)
if resp != "KG1Value" {
logNodeFailure(nodeA, "resp is \"KG1Value\"", resp)
}
logNodeAction(nodeA, "Getting a Value from a nonexistent keygroup")
nodeA.GetItem("trololoool", "wut", true)
logNodeAction(nodeA, "Putting a Value into a nonexistent keygroup")
nodeA.PutItem("nonexistentkeygroup", "item", "data", true)
logNodeAction(nodeA, "Putting new value KG1Item/KG1Value2 into KG1")
nodeA.PutItem("KG1", "KG1Item", "KG1Value2", false)
logNodeAction(nodeA, "Getting the value in KG1")
resp = nodeA.GetItem("KG1", "KG1Item", false)
if resp != "KG1Value2" {
logNodeFailure(nodeA, "resp is \"KG1Value2\"", resp)
}
logNodeAction(nodeA, "Getting all Replicas that nodeA has")
parsed := nodeA.GetAllReplica(false)
// Example Response: map[string]string
// {"nodeA": "1.2.3.4:5000", "nodeB": "4.5.6.7:4000"}
// Test for nodeA
if len(parsed) != 3 {
logNodeFailure(nodeA, "GetAllReplica returns 3 nodes", fmt.Sprintf("%d", len(parsed)))
}
addr, ok := parsed[nodeApeeringID]
if !ok {
logNodeFailure(nodeA, "GetAllReplica response contains nodeA", "nodeA not found")
} else if addr != fmt.Sprintf("%s:%s", nodeAhost, nodeAhttpPort) {
logNodeFailure(nodeA, "nodeA address is "+fmt.Sprintf("%s:%s", nodeAhost, nodeAhttpPort), addr)
}
addr, ok = parsed[nodeBpeeringID]
if !ok {
logNodeFailure(nodeA, "GetAllReplica response contains nodeB", "nodeB not found")
} else if addr != fmt.Sprintf("%s:%s", nodeBhost, nodeBhttpPort) {
logNodeFailure(nodeA, "nodeB address is "+fmt.Sprintf("%s:%s", nodeBhost, nodeBhttpPort), addr)
}
addr, ok = parsed[nodeCpeeringID]
if !ok {
logNodeFailure(nodeA, "GetAllReplica response contains nodeC", "nodeC not found")
} else if addr != fmt.Sprintf("%s:%s", nodeChost, nodeChttpPort) {
logNodeFailure(nodeA, "nodeC address is "+fmt.Sprintf("%s:%s", nodeChost, nodeChttpPort), addr)
}
// Fun with replicas
logNodeAction(nodeA, "Adding nodeB as Replica node for KG1")
nodeA.AddKeygroupReplica("KG1", nodeBpeeringID, 0, false)
logNodeAction(nodeB, "Deleting the value from KG1")
nodeB.DeleteItem("KG1", "KG1Item", false)
logNodeAction(nodeB, "Getting the deleted value in KG1")
_ = nodeB.GetItem("KG1", "KG1Item", true)
// Test sending data between nodes
logNodeAction(nodeB, "Creating a new Keygroup (KGN) in nodeB, setting nodeA as Replica node")
nodeB.CreateKeygroup("KGN", true, 0, false)
nodeB.AddKeygroupReplica("KGN", nodeApeeringID, 0, false)
logNodeAction(nodeB, "Putting something in KGN on nodeB, testing whether nodeA gets Replica (sleep 1.5s in between)")
nodeB.PutItem("KGN", "Item", "Value", false)
time.Sleep(1500 * time.Millisecond)
resp = nodeA.GetItem("KGN", "Item", false)
if resp != "Value" {
logNodeFailure(nodeA, "resp is \"Value\"", resp)
}
logNodeAction(nodeA, "Putting something in KGN on nodeA, testing whether nodeB gets Replica (sleep 1.5s in between)")
nodeA.PutItem("KGN", "Item2", "Value2", false)
time.Sleep(1500 * time.Millisecond)
resp = nodeB.GetItem("KGN", "Item2", false)
if resp != "Value2" {
logNodeFailure(nodeA, "resp is \"Value2\"", resp)
}
logNodeAction(nodeA, "Adding a replica for a nonexisting Keygroup")
nodeA.AddKeygroupReplica("trololololo", nodeBpeeringID, 0, true)
logNodeAction(nodeC, "Creating an already existing keygroup with another node")
nodeC.CreateKeygroup("KGN", true, 0, true)
logNodeAction(nodeC, "Telling a node that is not part of the keygroup that it is now part of that keygroup")
nodeC.AddKeygroupReplica("KGN", nodeCpeeringID, 0, false)
logNodeAction(nodeA, "Creating a new Keygroup (kgall) with all three nodes as replica")
nodeA.CreateKeygroup("kgall", true, 0, false)
nodeA.AddKeygroupReplica("kgall", nodeBpeeringID, 0, false)
nodeB.AddKeygroupReplica("kgall", nodeCpeeringID, 0, false)
logNodeAction(nodeC, "... sending data to one node, checking whether all nodes get the replica (sleep 1.5s)")
nodeC.PutItem("kgall", "item", "value", false)
time.Sleep(1500 * time.Millisecond)
respA := nodeA.GetItem("kgall", "item", false)
respB := nodeB.GetItem("kgall", "item", false)
if respA != "value" || respB != "value" {
logNodeFailure(nodeA, "both nodes respond with 'value'", fmt.Sprintf("NodeA: %s, NodeB: %s", respA, respB))
}
logNodeAction(nodeB, "...removing node from the keygroup all and checking whether it still has the data (sleep 1.5s)")
nodeB.DeleteKeygroupReplica("kgall", nodeBpeeringID, false)
time.Sleep(1500 * time.Millisecond)
respB = nodeB.GetItem("kgall", "item", true)
logNodeAction(nodeB, fmt.Sprintf("Got Response %s", respB))
logNodeAction(nodeB, "...re-adding the node to the keygroup all and checking whether it now gets the data (sleep 1.5s)")
nodeA.AddKeygroupReplica("kgall", nodeBpeeringID, 0, false)
time.Sleep(1500 * time.Millisecond)
respA = nodeA.GetItem("kgall", "item", false)
if respA != "value" {
logNodeFailure(nodeA, "resp is \"value\"", resp)
}
respB = nodeB.GetItem("kgall", "item", false)
if respB != "value" {
logNodeFailure(nodeB, "resp is \"value\"", resp)
}
// delete the last node from a keygroup
logNodeAction(nodeA, "Preparing to delete all members from a keygroup...")
nodeA.CreateKeygroup("deletetest", true, 0, false)
nodeA.PutItem("deletetest", "item", "value", false)
nodeA.AddKeygroupReplica("deletetest", nodeBpeeringID, 0, false)
nodeA.DeleteKeygroupReplica("deletetest", nodeApeeringID, false)
// NodeB is the only replica left
logNodeAction(nodeB, "Removing last member of a keygroup delete-test")
nodeB.DeleteKeygroupReplica("deletetest", nodeBpeeringID, true)
nodeB.PutItem("deletetest", "item", "value", false)
// let's test trigger nodes
// create a new keygroup on nodeA
logNodeAction(nodeA, "Creating keygroup triggertesting")
nodeA.CreateKeygroup("triggertesting", true, 0, false)
logNodeAction(nodeA, "Creating keygroup nottriggertesting")
nodeA.CreateKeygroup("nottriggertesting", true, 0, false)
//post an item1 to new keygroup
logNodeAction(nodeA, "post an item1 to new keygroup triggertesting")
nodeA.PutItem("triggertesting", "item1", "value1", false)
//add trigger node to nodeA
logNodeAction(nodeA, "add trigger node to nodeA for keygroup triggertesting")
nodeA.AddKeygroupTrigger("triggertesting", triggerNodeID, triggerNodeHost, false)
//post another item2 to new keygroup
logNodeAction(nodeA, "post another item2 to new keygroup triggertesting")
nodeA.PutItem("triggertesting", "item2", "value2", false)
//delete item1 from keygroup
logNodeAction(nodeA, "delete item1 from keygroup triggertesting")
nodeA.DeleteItem("triggertesting", "item1", false)
// post an item3 to keygroup nottriggertesting that should not be sent to trigger node
logNodeAction(nodeA, "post an item3 to keygroup nottriggertesting that should not be sent to trigger node")
nodeA.PutItem("nottriggertesting", "item3", "value3", false)
//add keygroup to nodeB as well
logNodeAction(nodeA, "add keygroup triggertesting to nodeB as well")
nodeA.AddKeygroupReplica("triggertesting", nodeBpeeringID, 0, false)
//post item4 to nodeB
logNodeAction(nodeB, "post item4 to nodeB in keygroup triggertesting")
nodeB.PutItem("triggertesting", "item4", "value4", false)
//remove trigger node from nodeA
logNodeAction(nodeA, "remove trigger node from nodeA in keygroup triggertesting")
nodeA.DeleteKeygroupTrigger("triggertesting", triggerNodeID, false)
//post item5 to nodeA
logNodeAction(nodeA, "post item5 to nodeA in keygroup triggertesting")
nodeA.PutItem("triggertesting", "item5", "value5", false)
// check logs from trigger node
// we should have the following logs (and nothing else):
// put triggertesting item2 value2
// del triggertesting item1
// put triggertesting item4 value4
logNodeAction(nodeA, "Checking if triggers have been executed correctly")
checkTriggerNode(triggerNodeID, triggerNodeWSHost)
logNodeAction(nodeA, "deleting keygroup triggertesting")
nodeA.DeleteKeygroup("triggertesting", false)
logNodeAction(nodeA, "deleting keygroup nottriggertesting")
nodeA.DeleteKeygroup("nottriggertesting", false)
logNodeAction(nodeA, "try to get the trigger nodes for keygroup triggertesting after deletion")
nodeA.GetKeygroupTriggers("triggertesting", true)
// testing immutable keygroups
logNodeAction(nodeB, "Testing immutable keygroups by creating a new immutable keygroup on nodeB")
nodeB.CreateKeygroup("log", false, 0, false)
logNodeAction(nodeB, "Creating an item in this keygroup")
res := nodeB.AppendItem("log", "value1", false)
if res != "0" {
logNodeFailure(nodeB, "0", res)
}
logNodeAction(nodeB, "Updating an item in this keygroup")
nodeB.PutItem("log", res, "value-2", true)
logNodeAction(nodeB, "Getting updated item from immutable keygroup")
respB = nodeB.GetItem("log", res, false)
if respB != "value1" {
logNodeFailure(nodeB, "resp is value1", respB)
}
logNodeAction(nodeB, "Deleting an item in immutable keygroup")
nodeB.DeleteItem("log", "testitem", true)
logNodeAction(nodeB, "Adding nodeC as replica to immutable keygroup")
nodeB.AddKeygroupReplica("log", nodeCpeeringID, 0, false)
logNodeAction(nodeC, "Updating immutable item on other nodeC")
nodeC.PutItem("log", "testitem", "value-3", true)
// TODO is this the right place???
logNodeAction(nodeC, "Appending another item to readonly log.")
res = nodeC.AppendItem("log", "value-2", false)
if res != "1" {
logNodeFailure(nodeB, "1", res)
}
// test expiring data items
logNodeAction(nodeC, "Create normal keygroup on nodeC without expiry")
nodeC.CreateKeygroup("expirytest", true, 0, false)
logNodeAction(nodeC, "Add nodeA as replica with expiry of 5s")
nodeC.AddKeygroupReplica("expirytest", nodeApeeringID, 5, false)
logNodeAction(nodeC, "Update something on nodeC")
nodeC.PutItem("expirytest", "test", "test", false)
logNodeAction(nodeA, "Test whether nodeA has received the update. Wait 5s and check that it is not there anymore")
nodeA.GetItem("expirytest", "test", false)
time.Sleep(5 * time.Second)
nodeA.GetItem("expirytest", "test", true)
logNodeAction(nodeC, "....the item should still exist with nodeC")
nodeC.GetItem("expirytest", "test", false)
// testing adding a node as a replica for a keygroup on itself
logNodeAction(nodeB, "Create and populate a new keygroup to test pulling")
nodeB.CreateKeygroup("pulltest", true, 0, false)
nodeB.PutItem("pulltest", "item1", "val1", false)
nodeB.PutItem("pulltest", "item2", "val2", false)
logNodeAction(nodeA, "add nodeA as a replica to that keygroup and see if it pulls the needed data on its own (sleep 3s)")
nodeA.AddKeygroupReplica("pulltest", nodeApeeringID, 0, false)
time.Sleep(3 * time.Second)
// check if the items exist
if res := nodeA.GetItem("pulltest", "item1", false); res != "val1" {
logNodeFailure(nodeA, "val1", res)
config := &Config{
waitUser: waitUser,
nodeAhost: nodeAhost,
nodeAhttpPort: nodeAhttpPort,
nodeApeeringID: nodeApeeringID,
nodeBhost: nodeBhost,
nodeBhttpPort: nodeBhttpPort,
nodeBpeeringID: nodeBpeeringID,
nodeChost: nodeChost,
nodeChttpPort: nodeChttpPort,
nodeCpeeringID: nodeCpeeringID,
triggerNodeHost: triggerNodeHost,
triggerNodeWSHost: triggerNodeWSHost,
triggerNodeID: triggerNodeID,
certFile: certFile,
keyFile: keyFile,
littleCertFile: littleCertFile,
littleKeyFile: littleKeyFile,
nodeA: nodeA,
nodeB: nodeB,
nodeC: nodeC,
littleClient: littleClient,
}
// to add a test suite, increase the size by one and add the instance of the suite to the slice
testSuites := make([]TestSuite, 7)
// initiate test suites
testSuites[0] = NewStandardSuite(config)
testSuites[1] = NewReplicaSuite(config)
testSuites[2] = NewTriggerSuite(config)
testSuites[3] = NewImmutableSuite(config)
testSuites[4] = NewExpirySuite(config)
testSuites[5] = NewSelfReplicaSuite(config)
testSuites[6] = NewAuthenticationSuite(config)
// parse testRange, starts at 1
minTest := 1
maxTest := len(testSuites)
testRangeSplit := strings.Split(testRange, "-")
if len(testRangeSplit[0]) > 0 {
minTestInput, errMin := strconv.Atoi(testRangeSplit[0])
if errMin == nil {
if minTestInput > minTest {
minTest = minTestInput
}
}
}
if res := nodeA.GetItem("pulltest", "item2", false); res != "val2" {
logNodeFailure(nodeA, "val2", res)
if len(testRangeSplit[1]) > 0 {
maxTestInput, errMax := strconv.Atoi(testRangeSplit[1])
if errMax == nil {
if maxTestInput < maxTest {
maxTest = maxTestInput
}
}
}
logNodeAction(nodeA, "Add an item on nodeA, check wheter it populates to nodeB")
nodeA.PutItem("pulltest", "item3", "val3", false)
// check if nodeB also gets that item
if res := nodeB.GetItem("pulltest", "item3", false); res != "val3" {
logNodeFailure(nodeB, "val3", res)
if minTest > maxTest {
minTest = maxTest
}
// test RBAC and authentication
logNodeAction(nodeA, "create keygroup \"rbactest\"")
nodeA.CreateKeygroup("rbactest", true, 0, false)
logNodeAction(nodeA, "put item into keygroup \"rbactest\"")
nodeA.PutItem("rbactest", "item1", "value1", false)
logNodeAction(nodeA, "add little client as read only to rbac test")
nodeA.AddUser("littleclient", "rbactest", "ReadKeygroup", false)
logNodeAction(nodeA, "try to read with little client -> should work")
littleClient := grpcclient.NewNode(nodeAhost, port, littleCertFile, littleKeyFile)
if val := littleClient.GetItem("rbactest", "item1", false); val != "value1" {
logNodeFailure(nodeA, "value1", val)
}
logNodeAction(nodeA, "try to write with little client -> should not work")
littleClient.PutItem("rbactest", "item1", "value2", true)
logNodeAction(nodeA, "add role configure replica to little client -> should work")
nodeA.AddUser("littleclient", "rbactest", "ConfigureReplica", false)
logNodeAction(nodeA, "add replica nodeB to keygroup with little client -> should work")
littleClient.AddKeygroupReplica("rbactest", nodeBpeeringID, 0, false)
logNodeAction(nodeB, "remove permission to read from keygroup -> should work")
nodeB.RemoveUser("littleclient", "rbactest", "ReadKeygroup", false)
logNodeAction(nodeA, "try to read from keygroup with little client -> should not work")
if val := littleClient.GetItem("rbactest", "item1", true); val != "" {
logNodeFailure(nodeA, "", val)
// run tests
// minTest and maxTest are indexed with 1 at the beginning, but the slice starts at 0
for i := minTest-1; i < maxTest ; i++ {
testSuites[i].RunTests()
}
// tally errors
totalerrors := nodeA.Errors + nodeB.Errors + nodeC.Errors + littleClient.Errors
if totalerrors > 0 {
......@@ -412,76 +164,6 @@ func logNodeFailure(node *grpcclient.Node, expected, result string) {
node.Errors++
}
func checkTriggerNode(triggerNodeID, triggerNodeWSHost string) {
log.Info().Str("trigger node", triggerNodeWSHost).Msg("Checking Trigger Node logs")
type LogEntry struct {
Op string `json:"op"`
Kg string `json:"kg"`
ID string `json:"id"`
Val string `json:"val"`
}
// put triggertesting item2 value2
// del triggertesting item1
// put triggertesting item4 value4
expected := make([]LogEntry, 3)
expected[0] = LogEntry{
Op: "put",
Kg: "triggertesting",
ID: "item2",
Val: "value2",
}
expected[1] = LogEntry{
Op: "del",
Kg: "triggertesting",
ID: "item1",
}
expected[2] = LogEntry{