UNPKG

recoder-code

Version:

Complete AI-powered development platform with ML model training, plugin registry, real-time collaboration, monitoring, infrastructure automation, and enterprise deployment capabilities

177 lines (139 loc) 4.36 kB
json0 = require '../lib/json0' {randomInt, randomReal, randomWord} = require 'ot-fuzzer' # This is an awful function to clone a document snapshot for use by the random # op generator. .. Since we don't want to corrupt the original object with # the changes the op generator will make. clone = (o) -> JSON.parse(JSON.stringify(o)) randomKey = (obj) -> if Array.isArray(obj) if obj.length == 0 undefined else randomInt obj.length else count = 0 for key of obj result = key if randomReal() < 1/++count result # Generate a random new key for a value in obj. # obj must be an Object. randomNewKey = (obj) -> # There's no do-while loop in coffeescript. key = randomWord() key = randomWord() while obj[key] != undefined key # Generate a random object randomThing = -> switch randomInt 6 when 0 then null when 1 then '' when 2 then randomWord() when 3 obj = {} obj[randomNewKey(obj)] = randomThing() for [1..randomInt(5)] obj when 4 then (randomThing() for [1..randomInt(5)]) when 5 then randomInt(50) # Pick a random path to something in the object. randomPath = (data) -> path = [] while randomReal() > 0.85 and typeof data == 'object' key = randomKey data break unless key? path.push key data = data[key] path module.exports = genRandomOp = (data) -> pct = 0.95 container = data: clone data op = while randomReal() < pct pct *= 0.6 # Pick a random object in the document operate on. path = randomPath(container['data']) # parent = the container for the operand. parent[key] contains the operand. parent = container key = 'data' for p in path parent = parent[key] key = p operand = parent[key] if randomReal() < 0.4 and parent != container and Array.isArray(parent) # List move newIndex = randomInt parent.length # Remove the element from its current position in the list parent.splice key, 1 # Insert it in the new position. parent.splice newIndex, 0, operand {p:path, lm:newIndex} else if randomReal() < 0.3 or operand == null # Replace newValue = randomThing() parent[key] = newValue if Array.isArray(parent) {p:path, ld:operand, li:clone(newValue)} else {p:path, od:operand, oi:clone(newValue)} else if typeof operand == 'string' # String. This code is adapted from the text op generator. if randomReal() > 0.5 or operand.length == 0 # Insert pos = randomInt(operand.length + 1) str = randomWord() + ' ' path.push pos parent[key] = operand[...pos] + str + operand[pos..] c = {p:path, si:str} else # Delete pos = randomInt(operand.length) length = Math.min(randomInt(4), operand.length - pos) str = operand[pos...(pos + length)] path.push pos parent[key] = operand[...pos] + operand[pos + length..] c = {p:path, sd:str} if json0._testStringSubtype # Subtype subOp = {p:path.pop()} if c.si? subOp.i = c.si else subOp.d = c.sd c = {p:path, t:'text0', o:[subOp]} c else if typeof operand == 'number' # Number inc = randomInt(10) - 3 parent[key] += inc {p:path, na:inc} else if Array.isArray(operand) # Array. Replace is covered above, so we'll just randomly insert or delete. # This code looks remarkably similar to string insert, above. if randomReal() > 0.5 or operand.length == 0 # Insert pos = randomInt(operand.length + 1) obj = randomThing() path.push pos operand.splice pos, 0, obj {p:path, li:clone(obj)} else # Delete pos = randomInt operand.length obj = operand[pos] path.push pos operand.splice pos, 1 {p:path, ld:clone(obj)} else # Object k = randomKey(operand) if randomReal() > 0.5 or not k? # Insert k = randomNewKey(operand) obj = randomThing() path.push k operand[k] = obj {p:path, oi:clone(obj)} else obj = operand[k] path.push k delete operand[k] {p:path, od:clone(obj)} [op, container.data]