| 395 | |
| 396 | |
| 397 | void fuzzJSONObject( |
| 398 | const std::shared_ptr<JSONNode> & node, |
| 399 | WriteBuffer & out, |
| 400 | const StorageFuzzJSON::Configuration & config, |
| 401 | pcg64 & rnd, |
| 402 | size_t depth, |
| 403 | size_t & node_count) |
| 404 | { |
| 405 | checkStackSize(); |
| 406 | |
| 407 | ++node_count; |
| 408 | |
| 409 | bool should_fuzz = rnd() % 100 < 100 * config.probability; |
| 410 | |
| 411 | const auto & next_node = should_fuzz && !config.should_reuse_output ? std::make_shared<JSONNode>(*node) : node; |
| 412 | |
| 413 | if (should_fuzz) |
| 414 | fuzzSingleJSONNode(*next_node, config, rnd, depth, node_count); |
| 415 | |
| 416 | if (next_node->key) |
| 417 | { |
| 418 | writeDoubleQuoted(*next_node->key, out); |
| 419 | out << fuzzJSONStructure(config, rnd, ":"); |
| 420 | } |
| 421 | |
| 422 | auto & val = next_node->value; |
| 423 | |
| 424 | if (val.fixed) |
| 425 | { |
| 426 | if (val.fixed->getType() == Field::Types::Which::String) |
| 427 | { |
| 428 | out << fuzzJSONStructure(config, rnd, "\""); |
| 429 | writeText(val.fixed->safeGet<String>(), out); |
| 430 | out << fuzzJSONStructure(config, rnd, "\""); |
| 431 | } |
| 432 | else |
| 433 | writeFieldText(*val.fixed, out); |
| 434 | } |
| 435 | else |
| 436 | { |
| 437 | if (!val.array && !val.object) |
| 438 | return; |
| 439 | |
| 440 | const auto & [op, cl, node_list] = val.array ? std::make_tuple("[", "]", *val.array) : std::make_tuple("{", "}", *val.object); |
| 441 | |
| 442 | out << fuzzJSONStructure(config, rnd, op); |
| 443 | |
| 444 | bool first = true; |
| 445 | for (const auto & ptr : node_list) |
| 446 | { |
| 447 | if (node_count >= StorageFuzzJSON::Configuration::value_number_limit) |
| 448 | break; |
| 449 | |
| 450 | WriteBufferFromOwnString child_out; |
| 451 | if (!first) |
| 452 | child_out << fuzzJSONStructure(config, rnd, ", "); |
| 453 | first = false; |
| 454 |
no test coverage detected