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

assertEquals doesn't work for large arrays #5942

Open
sigmaSd opened this issue Sep 11, 2024 · 3 comments
Open

assertEquals doesn't work for large arrays #5942

sigmaSd opened this issue Sep 11, 2024 · 3 comments
Labels
bug Something isn't working needs triage

Comments

@sigmaSd
Copy link
Contributor

sigmaSd commented Sep 11, 2024

import { assertEquals } from "jsr:@std/assert@1";
const a = Deno.readFileSync(Deno.execPath());
assertEquals(a, new Uint8Array());

deno -R a.ts

error: Uncaught (in promise) RangeError: Invalid array length
      if (Object.keys(a).length !== Object.keys(b).length) {
@sigmaSd sigmaSd added bug Something isn't working needs triage labels Sep 11, 2024
@kt3k
Copy link
Member

kt3k commented Sep 13, 2024

Does the utility like this make more sense to such cases? https://github.com/fent/node-stream-equal

@sigmaSd
Copy link
Contributor Author

sigmaSd commented Sep 15, 2024

I'm not sure it feels weird to me that an assert equal doesn't work after a certain size, also the error is not helpful

@lionel-rowe
Copy link
Contributor

lionel-rowe commented Sep 23, 2024

It'd probably make sense to have a separate path for iterables and/or array-likes.

type Iter<T> = { [Symbol.iterator](): Iterator<T> };
type TypedArrayLike = Iter<number | bigint>;
function isTypedArray(x: unknown): x is TypedArrayLike {
    return ArrayBuffer.isView(x) && Symbol.iterator in x;
}

function iterEqual<T>(a: Iter<T>, b: Iter<T>, eq: (a: T, b: T) => boolean): boolean {
    if (a === b) return true;
    if (a.constructor !== b.constructor) return false;
    // @ts-expect-error - if no `length` prop we just check both undefined
    if (a.length !== b.length) return false;
    
    const aIter = a[Symbol.iterator]();
    const bIter = b[Symbol.iterator]();
    
    while (true) {
        const aNext = aIter.next();
        const bNext = bIter.next();
        if (aNext.done !== bNext.done) return false;
        if (!eq(aNext.value, bNext.value)) return false;
        if (aNext.done) return true;
    }
}

function typedArrayEqual(a: TypedArrayLike, b: TypedArrayLike): boolean {
    return iterEqual(a, b, (a, b) => a === b);
}

const bytes = Deno.readFileSync(Deno.execPath());
const diffAtStart = bytes.slice();
++diffAtStart[0];
const diffAtEnd = bytes.slice();
++diffAtEnd[diffAtEnd.length - 1];

console.time();
// true
console.log(typedArrayEqual(bytes, bytes));
// 0ms
console.timeEnd();

console.time();
// true
console.log(typedArrayEqual(bytes, bytes.slice()));
// 3562ms
console.timeEnd();

console.time();
// false
console.log(typedArrayEqual(bytes, diffAtStart));
// 0ms
console.timeEnd();

console.time();
// false
console.log(typedArrayEqual(bytes, diffAtEnd));
// 3381ms
console.timeEnd();

console.time();
// false
console.log(typedArrayEqual(bytes, new Uint8Array(0)));
// 0ms
console.timeEnd();

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working needs triage
Projects
None yet
Development

No branches or pull requests

3 participants