Skip to content

Commit

Permalink
first commit
Browse files Browse the repository at this point in the history
Signed-off-by: jace-roell <[email protected]>
  • Loading branch information
jace-roell committed Nov 15, 2024
1 parent ad53d44 commit 4ae2ccf
Show file tree
Hide file tree
Showing 7 changed files with 283 additions and 9 deletions.
16 changes: 16 additions & 0 deletions packages/imperative/src/io/__tests__/IO.unit.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -276,6 +276,22 @@ describe("IO tests", () => {
expect(processed).toBe(original.replace(/\n/g, "\r\n").slice(1));
});

it("processNewlines should replace LF line endings with CRLF on Windows when input is a Buffer", () => {
jest.spyOn(os, "platform").mockReturnValueOnce(IO.OS_WIN32);
const originalBuffer = Buffer.from("\nabc\ndef\n");
const processedBuffer = IO.processNewlines(originalBuffer);
const expectedBuffer = Buffer.from("\r\nabc\r\ndef\r\n");
expect(processedBuffer.equals(expectedBuffer)).toBe(true);
});

it("processNewlines should not replace LF line ending when last byte is CR and input is a Buffer", () => {
jest.spyOn(os, "platform").mockReturnValueOnce(IO.OS_WIN32);
const originalBuffer = Buffer.from("\nabc\ndef\n");
const processedBuffer = IO.processNewlines(originalBuffer, "\r".charCodeAt(0));
const expectedBuffer = Buffer.from("\nabc\r\ndef\r\n");
expect(processedBuffer.equals(expectedBuffer)).toBe(true);
});

it("should get an error for no input on mkdirp", () => {
let error;
try {
Expand Down
33 changes: 27 additions & 6 deletions packages/imperative/src/io/src/IO.ts
Original file line number Diff line number Diff line change
Expand Up @@ -264,17 +264,38 @@ export class IO {
* @returns {string} - input with removed newlines
* @memberof IO
*/
public static processNewlines(original: string, lastByte?: number): string {
public static processNewlines<T extends string | Buffer>(original: T, lastByte?: number): T {
ImperativeExpect.toNotBeNullOrUndefined(original, "Required parameter 'original' must not be null or undefined");

if (os.platform() !== IO.OS_WIN32) {
return original;
}
// otherwise, we're on windows
const processed = original.replace(/([^\r])\n/g, "$1\r\n");
if ((lastByte == null || lastByte !== "\r".charCodeAt(0)) && original.startsWith("\n")) {
return "\r" + processed;

let processed: T;

if (typeof original === "string") {
processed = original.replace(/([^\r])\n/g, "$1\r\n") as T;
if ((lastByte == null || lastByte !== "\r".charCodeAt(0)) && original.startsWith("\n")) {
return ("\r" + processed) as T;
}
return processed;
} else {
// Create worst-case scenario sized buffer
const bufferList = Buffer.alloc(original.length * 2);
let bufferIndex = 0;
let prevByte = lastByte;
for (let i = 0; i < original.length; i++) {
const currentByte = original[i];
if (prevByte !== 13 && currentByte === 10) {
bufferList[bufferIndex++] = 13;
}
bufferList[bufferIndex++] = currentByte;
prevByte = currentByte;
}
// Create a buffer slice of the actual used portion
processed = bufferList.slice(0, bufferIndex) as T;
return processed;
}
return processed;
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -766,7 +766,7 @@ export abstract class AbstractRestClient {
this.log.debug("Streaming data chunk of length " + respData.length + " to response stream");
if (this.mNormalizeResponseNewlines && this.mContentEncoding == null) {
this.log.debug("Normalizing new lines in data chunk to operating system appropriate line endings");
respData = Buffer.from(IO.processNewlines(respData.toString(), this.lastByteReceived));
respData = IO.processNewlines(respData, this.lastByteReceived);
}
if (this.mTask != null) {
// update the progress task if provided by the requester
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ export class CompressionUtils {
let lastByteReceived: number = 0;
return new Transform({
transform(chunk, _, callback) {
this.push(Buffer.from(IO.processNewlines(chunk.toString(), lastByteReceived)));
this.push(IO.processNewlines(chunk, lastByteReceived));
lastByteReceived = chunk[chunk.byteLength - 1];
callback();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,9 @@ const rimraf = require("rimraf").sync;
const delayTime = 2000;
const testData = "abcdefghijklmnopqrstuvwxyz";

// File must be larger than 8KB such that it breaks into multiple chunks
const specialCharTestData = fs.readFileSync(__dirname+"/testfiles/specialCharTestData.txt");

let REAL_SESSION: Session;
let testEnvironment: ITestEnvironment<ITestPropertiesSchema>;
let defaultSystem: ITestPropertiesSchema;
Expand Down Expand Up @@ -574,6 +577,40 @@ describe("Download Data Set", () => {
const regex = /\./gi;
file = dsname.replace(regex, "/") + "/member.dat";
});
it("should download a data set member full of special characters to test buffer chunk concatenation", async () => {
let error;
let response: IZosFilesResponse;

// upload data to the newly created data set
await Upload.bufferToDataSet(REAL_SESSION, Buffer.from(specialCharTestData), dsname + "(member)");
await delay(delayTime);

try {
response = await Download.allMembers(REAL_SESSION, dsname);
Imperative.console.info("Response: " + inspect(response));
} catch (err) {
error = err;
Imperative.console.info("Error: " + inspect(error));
}
expect(error).toBeFalsy();
expect(response).toBeTruthy();
expect(response.success).toBeTruthy();
expect(response.commandResponse).toContain(
ZosFilesMessages.datasetDownloadedSuccessfully.message.substring(0, "Data set downloaded successfully".length + 1));

// Convert the data set name to use as a path/file
const regex = /\./gi;
file = dsname.replace(regex, "/");
file = file.toLowerCase();

// Compare the downloaded contents to those uploaded
const fileContents = stripNewLines(fs.readFileSync(`${file}/member.txt`).toString());
const uniqueFileChars = Array.from(new Set(fileContents)).join('');
const expectedUniqueChars = "àèéìòùÀÈÉÌÒÙ° "; // Expected unique characters

// Ensure the file only contains the unique characters and nothing else
expect(uniqueFileChars).toEqual(expectedUniqueChars);
});
});

describe("Data sets matching - all data sets - PO", () => {
Expand Down
Loading

0 comments on commit 4ae2ccf

Please sign in to comment.