Skip to content

Commit

Permalink
refactor: Remove some nesting and simplify code, add tests. (#195)
Browse files Browse the repository at this point in the history
* test: Add test cases for logs processing and logs merging.

* refactor: Removing extra nesting, plus better code for solutiontype that works with both Cloud Logging and Bigquery.
  • Loading branch information
regeter authored Nov 28, 2024
1 parent 3eb93bd commit f563822
Show file tree
Hide file tree
Showing 2 changed files with 128 additions and 57 deletions.
102 changes: 45 additions & 57 deletions src/localStorage.js
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ async function processJsonFile(file) {
});
}

function parseJsonContent(content) {
export function parseJsonContent(content) {
console.log("Parsing JSON content");
try {
return JSON.parse(content);
Expand All @@ -91,7 +91,7 @@ function parseJsonContent(content) {
}
}

function removeEmptyObjects(obj) {
export function removeEmptyObjects(obj) {
Object.keys(obj).forEach((key) => {
if (obj[key] && typeof obj[key] === "object") {
if (Object.keys(obj[key]).length === 0) {
Expand All @@ -108,70 +108,58 @@ function isRestrictedLog(log) {
return log.jsonPayload?.["@type"]?.includes("Restricted") || false;
}

function ensureCorrectFormat(data) {
export function ensureCorrectFormat(data) {
if (data && Array.isArray(data.rawLogs)) {
return {
...data,
APIKEY: data.APIKEY || DEFAULT_API_KEY,
};
} else {
const logsArray = Array.isArray(data) ? data : [data];

const restrictedLogsMap = new Map();
logsArray.forEach((log) => {
if (isRestrictedLog(log)) {
removeEmptyObjects(log.jsonPayload);
restrictedLogsMap.set(log.jsonPayload.parentInsertId, log);
}
});
}
const logsArray = Array.isArray(data) ? data : [data];

// Filter out restricted logs while merging their TOS-restricted attributes into their parent logs.
const mergedLogs = logsArray.filter((log) => {
if (isRestrictedLog(log)) {
return false;
}
const restrictedLog = restrictedLogsMap.get(log.insertId)?.jsonPayload;
if (restrictedLog) {
["request", "response"].forEach((section) => {
if (restrictedLog[section] && log.jsonPayload[section]) {
TOS_RESTRICTED_ATTRIBUTES.forEach((attr) => {
if (restrictedLog[section][attr] !== undefined) {
log.jsonPayload[section][attr] = restrictedLog[section][attr];
}
});
}
});
}
return true;
});

// Determine the solution type based on the resource type of the first log entry
const firstLog = mergedLogs[0];
const resourceType = firstLog?.resource?.type;
let solutionType;

if (resourceType === "fleetengine.googleapis.com/DeliveryFleet") {
solutionType = "LMFS";
} else if (resourceType === "fleetengine.googleapis.com/Fleet") {
solutionType = "ODRD";
} else {
console.warn(
`Unknown resource type: ${resourceType}, defaulting to ODRD`
);
solutionType = "ODRD";
const restrictedLogsMap = new Map();
logsArray.forEach((log) => {
if (isRestrictedLog(log)) {
removeEmptyObjects(log.jsonPayload);
restrictedLogsMap.set(log.jsonPayload.parentInsertId, log);
}
});

console.log(`Determined solution type: ${solutionType}`);
// Filter out restricted logs while merging their TOS-restricted attributes into their parent logs.
const mergedLogs = logsArray.filter((log) => {
if (isRestrictedLog(log)) {
return false;
}
const restrictedLog = restrictedLogsMap.get(log.insertId)?.jsonPayload;
if (restrictedLog) {
["request", "response"].forEach((section) => {
if (restrictedLog[section] && log.jsonPayload[section]) {
TOS_RESTRICTED_ATTRIBUTES.forEach((attr) => {
if (restrictedLog[section][attr] !== undefined) {
log.jsonPayload[section][attr] = restrictedLog[section][attr];
}
});
}
});
}
return true;
});

return {
APIKEY: DEFAULT_API_KEY,
vehicle: "",
projectId: "",
logSource: "Direct Cloud Logging",
solutionType: solutionType,
rawLogs: mergedLogs,
};
}
// Determine the solution type based on the presence of _delivery_vehicle logs
const isLMFS = mergedLogs.some((log) =>
log.logName?.includes("_delivery_vehicle")
);
const solutionType = isLMFS ? "LMFS" : "ODRD";
console.log(`Determined solution type: ${solutionType}`);

return {
APIKEY: DEFAULT_API_KEY,
vehicle: "",
projectId: "",
logSource: "Direct Cloud Logging",
solutionType: solutionType,
rawLogs: mergedLogs,
};
}

async function saveToIndexedDB(data, index) {
Expand Down
83 changes: 83 additions & 0 deletions src/localStorage.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
// localStorage.test.js
import fs from "fs";
import { parseJsonContent, removeEmptyObjects, ensureCorrectFormat } from "./localStorage";

// Helper function to load test data
function loadTestData(filename) {
return JSON.parse(fs.readFileSync(`./datasets/${filename}`));
}

test("parseJsonContent handles valid JSON", () => {
const validJson = JSON.stringify({ test: "data" });
const result = parseJsonContent(validJson);
expect(result).toStrictEqual({ test: "data" });
});

test("parseJsonContent handles multiple JSON objects", () => {
const multipleJson = '{"test": "data1"},{"test": "data2"}';
const result = parseJsonContent(multipleJson);
expect(result).toHaveLength(2);
expect(result[0]).toStrictEqual({ test: "data1" });
expect(result[1]).toStrictEqual({ test: "data2" });
});

test("parseJsonContent handles JSON array", () => {
const arrayJson = '[{"key": "value1"},{"test": "data2"}]';
const result = parseJsonContent(arrayJson);
expect(result).toHaveLength(2);
expect(result[0]).toStrictEqual({ key: "value1" });
expect(result[1]).toStrictEqual({ test: "data2" });
});

test("parseJsonContent throws error for invalid JSON", () => {
const invalidJson = "{invalid}";
expect(() => parseJsonContent(invalidJson)).toThrow("Invalid JSON content");
});

test("removeEmptyObjects removes empty nested objects", () => {
const input = {
a: {},
b: { c: {}, d: { e: 1 } }
};
const expected = {
b: { d: { e: 1 } }
};
expect(removeEmptyObjects(input)).toStrictEqual(expected);
});

test("ensureCorrectFormat handles LMFS logs", () => {
const lmfsData = loadTestData("lmfs.json");
const result = ensureCorrectFormat(lmfsData.rawLogs);
expect(result.solutionType).toBe("LMFS");
});

test("ensureCorrectFormat handles ODRD logs", () => {
const odrdData = loadTestData("jump-demo.json");
const result = ensureCorrectFormat(odrdData.rawLogs);
expect(result.solutionType).toBe("ODRD");
});

test("ensureCorrectFormat merges restricted attributes", () => {
const parentLog = {
insertId: "parent",
jsonPayload: {
"@type": "type.googleapis.com/Normal",
request: {},
response: {}
}
};

const restrictedLog = {
jsonPayload: {
"@type": "type.googleapis.com/Restricted",
parentInsertId: "parent",
request: {
waypoints: ["point1", "point2"]
}
}
};

const result = ensureCorrectFormat([parentLog, restrictedLog]);
expect(result.rawLogs[0].jsonPayload.request.waypoints).toStrictEqual(["point1", "point2"]);
expect(result.rawLogs.length).toBe(1);
});

0 comments on commit f563822

Please sign in to comment.