All files / json-crdt-patch/codec/__tests__ PatchFuzzer.ts

92.85% Statements 52/56
100% Branches 0/0
96.66% Functions 29/30
92.72% Lines 51/55

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 1011x 1x 1x     1x   1x   800x 800x 800x 800x       800x 800x 800x 800x       1600x 1600x 16873x 1143x 1104x 1109x 1153x 1137x 1089x 1090x   1166x   6454x   1130x 1081x 1136x   1155x     6482x   1081x 1146x 1153x   16873x   1600x       800x 800x 800x       800x     1x 14632x 14632x 14632x     1x 15164x 15164x     1x               800x       1600x       3373x       1600x      
import {RandomJson} from '@jsonjoy.com/util/lib/json-random';
import {Fuzzer} from '@jsonjoy.com/util/lib/Fuzzer';
import {interval, type ITimestampStruct, Timespan, ClockVector, ServerClockVector, ts} from '../../clock';
import {SESSION} from '../../constants';
import type {Patch} from '../../Patch';
import {PatchBuilder} from '../../PatchBuilder';
 
export class PatchFuzzer extends Fuzzer {
  public generateLogicalPatch(): Patch {
    const clock = this.generateLogicalClock();
    const builder = new PatchBuilder(clock);
    this.generateLogicalPatchBase(builder, this.generateLogicalTimestamp);
    return builder.patch;
  }
 
  public generateServerPatch(): Patch {
    const clock = this.generateServerClock();
    const builder = new PatchBuilder(clock);
    this.generateLogicalPatchBase(builder, this.generateServerTimestamp);
    return builder.patch;
  }
 
  public generateLogicalPatchBase(builder: PatchBuilder, ts: () => ITimestampStruct): Patch {
    const length = this.generatePatchLength();
    for (let i = 0; i < length; i++) {
      const build = Fuzzer.pick([
        () => builder.obj(),
        () => builder.arr(),
        () => builder.str(),
        () => builder.bin(),
        () => builder.val(),
        () => builder.con(RandomJson.generate()),
        () => builder.root(ts()),
        () =>
          builder.insObj(
            ts(),
            Fuzzer.repeat(Fuzzer.randomInt(1, 10), () => [RandomJson.genString(), ts()]),
          ),
        () => builder.setVal(ts(), ts()),
        () => builder.insStr(ts(), ts(), RandomJson.genString()),
        () => builder.insBin(ts(), ts(), RandomJson.genBinary()),
        () =>
          builder.insArr(
            ts(),
            ts(),
            Fuzzer.repeat(Fuzzer.randomInt(1, 10), () => ts()),
          ),
        () => builder.del(ts(), [interval(ts(), 0, this.generateSpan())]),
        () => builder.del(ts(), [interval(ts(), 0, this.generateSpan()), interval(ts(), 0, this.generateSpan())]),
        () => builder.nop(Fuzzer.randomInt(1, 20)),
      ]);
      build();
    }
    return builder.patch;
  }
 
  public generateLogicalClock(): ClockVector {
    const sessionId = this.generateSessionId();
    const time = this.generateTime();
    return new ClockVector(sessionId, time);
  }
 
  public generateServerClock(): ServerClockVector {
    return new ServerClockVector(SESSION.SERVER, this.generateTime());
  }
 
  public readonly generateLogicalTimestamp = (): ITimestampStruct => {
    const sessionId = Fuzzer.randomInt(0xffff + 1, SESSION.MAX);
    const time = Fuzzer.randomInt(0, 0xffffff);
    return ts(sessionId, time);
  };
 
  public readonly generateServerTimestamp = (): ITimestampStruct => {
    const time = Fuzzer.randomInt(0, 0xffffff);
    return ts(SESSION.SERVER, time);
  };
 
  public readonly generateLogicalTimespan = (): Timespan => {
    const sessionId = this.generateSessionId();
    const time = this.generateTime();
    const span = this.generateSpan();
    return new Timespan(sessionId, time, span);
  };
 
  public generateSessionId(): number {
    return Fuzzer.randomInt(0xffff + 1, SESSION.MAX);
  }
 
  public generateTime(): number {
    return Fuzzer.randomInt(0, 0xffffffffff);
  }
 
  public generateSpan(): number {
    return Fuzzer.randomInt(1, 0xffff);
  }
 
  public generatePatchLength(): number {
    return Fuzzer.randomInt(1, 20);
  }
}