Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: compression errror returns empty array #76

Merged
merged 3 commits into from
Oct 5, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions common/protocol/src/methods/validate/saveBundleDecompress.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,21 +22,21 @@ export async function saveBundleDecompress(

this.logger.debug(`this.compression.decompress($RAW_STORAGE_DATA)`);

const storageBundle = bytesToBundle(
await compression.decompress(rawStorageData)
);
const decompressed: Buffer = await compression.decompress(rawStorageData);

const storageBundle: DataItem[] = bytesToBundle(decompressed);

this.logger.info(
`Successfully decompressed bundle with Compression:${compression.name}`
);

return standardizeError(storageBundle);
return storageBundle;
} catch (err) {
this.logger.error(
`Could not decompress bundle with Compression. Continuing ...`
);
this.logger.error(standardizeError(err));
this.logger.error(err);

return [];
throw err;
}
}
12 changes: 6 additions & 6 deletions common/protocol/src/methods/validate/validateBundleProposal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -137,13 +137,13 @@ export async function validateBundleProposal(

// if storage provider result is empty skip runtime validation
if (storageProviderResult.byteLength) {
// decompress the bundle with the specified compression type
// and convert the bytes into a JSON format
const proposedBundle = await this.saveBundleDecompress(
storageProviderResult
);

try {
// decompress the bundle with the specified compression type
// and convert the bytes into a JSON format
const proposedBundle = await this.saveBundleDecompress(
storageProviderResult
);

// perform custom runtime bundle validation
this.logger.debug(
`Validating bundle proposal by custom runtime validation`
Expand Down
123 changes: 123 additions & 0 deletions common/protocol/test/compression.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
import { Logger } from "tslog";
import { ICompression, IStorageProvider, Validator } from "../src/index";
import { client } from "./mocks/client.mock";
import { lcd } from "./mocks/lcd.mock";
import { TestCacheProvider } from "./mocks/cache.mock";
import { setupMetrics } from "../src/methods";
import { register } from "prom-client";
import { TestRuntime } from "./mocks/runtime.mock";
import { TestNormalStorageProvider } from "./mocks/storageProvider.mock";
import { TestNormalCompression } from "./mocks/compression.mock";
import { Gzip } from "../src/reactors/compression/Gzip";

/*

TEST CASES - compression tests

* Valid parsing
* Invalid parsing
* Valid gzip compression and decompression

*/

describe("compression tests", () => {
let v: Validator;

let processExit: jest.Mock<never, never>;
let setTimeoutMock: jest.Mock;

let storageProvider: IStorageProvider;
let compression: ICompression;

beforeEach(() => {
v = new Validator(new TestRuntime());

v["cacheProvider"] = new TestCacheProvider();

// mock storage provider
storageProvider = new TestNormalStorageProvider();
v["storageProviderFactory"] = jest.fn().mockReturnValue(storageProvider);

// mock compression
compression = new TestNormalCompression();
v["compressionFactory"] = jest.fn().mockReturnValue(compression);

// mock process.exit
processExit = jest.fn<never, never>();
process.exit = processExit;

// mock setTimeout
setTimeoutMock = jest
.fn()
.mockImplementation(
(
callback: (args: void) => void,
ms?: number | undefined
): NodeJS.Timeout => {
callback();
return null as any;
}
);
global.setTimeout = setTimeoutMock as any;

// mock logger
v.logger = new Logger({ minLevel: "warn" });

v["poolId"] = 0;
v["staker"] = "test_staker";

v["rpc"] = ["http://0.0.0.0:26657"];
v.client = [client()];

v["rest"] = ["http://0.0.0.0:1317"];
v.lcd = [lcd()];

v["continueRound"] = jest
.fn()
.mockReturnValueOnce(true)
.mockReturnValue(false);

v["waitForCacheContinuation"] = jest.fn();

setupMetrics.call(v);
});

afterEach(() => {
// reset prometheus
register.clear();
});

test("Valid parsing", async () => {
const fill =
"[{\"key\": \"key1\",\"value\": \"value1\"}, {\"key\": \"key2\",\"value\": \"value2\"}]";
// using array call for function as it is protected
const parsed = await v["saveBundleDecompress"](
Buffer.alloc(fill.length, fill)
);

expect(parsed).toEqual(JSON.parse(fill));
expect(parsed.length).toEqual(2);
});

test("Invalid parsing", async () => {
const fill = "Invalid JSON";

// using array call for function as it is protected
await expect(
v["saveBundleDecompress"](Buffer.alloc(fill.length, fill))
).rejects.toThrow();
});

// GZIP

test("Valid gzip compression and decompression", async () => {
const fill =
"[{\"key\": \"key1\",\"value\": \"value1\"}, {\"key\": \"key2\",\"value\": \"value2\"}]";

const gzipper = new Gzip();
const zipped = await gzipper.compress(Buffer.alloc(fill.length, fill));
const unzipped = await gzipper.decompress(zipped);

expect(fill).toEqual(unzipped.toString());
});
});