public Operation nextOperation()

in firebase-database/src/testUtil/java/com/google/firebase/database/core/RandomOperationGenerator.java [115:205]


  public Operation nextOperation() {
    if (this.writeOpForLastUpdate != null) {
      return getAck();
    }
    if (random.nextDouble() < SERVER_OP_PROBABILITY) {
      if (this.completeDataJustSentForListen != null) {
        Path path = this.completeDataJustSentForListen.getPath();
        QueryParams params = this.completeDataJustSentForListen.getParams();
        OperationSource source;
        if (!params.loadsAllData()) {
          source =
              OperationSource.forServerTaggedQuery(this.completeDataJustSentForListen.getParams());
        } else {
          source = OperationSource.SERVER;
        }
        completeDataJustSentForListen = null;
        return new ListenComplete(source, path);
      } else if (!outstandingListens.isEmpty()
          && random.nextDouble() < SERVER_LISTEN_RESPONSE_PROBABILITY) {
        QuerySpec listen = outstandingListens.poll();
        QueryParams params = listen.getParams();
        Path path = listen.getPath();
        Node currentServerNode = this.currentServerState.getChild(path);
        if (!params.loadsAllData()) {
          IndexedNode emptyNode = IndexedNode.from(EmptyNode.Empty(), params.getIndex());
          IndexedNode node =
              params
                  .getNodeFilter()
                  .updateFullNode(
                      emptyNode, IndexedNode.from(currentServerNode, params.getIndex()), null);
          OperationSource source = OperationSource.forServerTaggedQuery(listen.getParams());
          return new Overwrite(source, path, node.getNode());
        } else {
          return new Overwrite(OperationSource.SERVER, path, currentServerNode);
        }
      } else if (!outstandingUnlistens.isEmpty()
          && random.nextDouble() < SERVER_LISTEN_RESPONSE_PROBABILITY) {
        throw new RuntimeException("NOT IMPL!");
      } else if (outstandingWrites.size() > 0 && random.nextDouble() < SERVER_ACK_PROBABILITY) {
        WriteOp op = outstandingWrites.peek();
        Path path = op.operation.getPath();
        boolean isEmptyPriorityError =
            !path.isEmpty()
                && path.getBack().isPriorityChildName()
                && this.currentServerState.getChild(path.getParent()).isEmpty();
        if (random.nextDouble() < REVERT_PROBABILITY || isEmptyPriorityError) {
          writeTree.removeWrite(op.writeId);
          outstandingWrites.remove();
          return getAckForWrite(op.operation, /*revert=*/ true);
        } else {
          // TODO: maybe ignore if write equals server data
          Operation serverOp = userOperationToServerOperation(op.operation);
          this.currentServerState = applyOperation(serverOp, this.currentServerState);
          this.writeOpForLastUpdate = op;
          return serverOp;
        }
      } else {
        if (random.nextDouble() < MERGE_PROBABILITY) {
          Merge merge = getRandomMerge(OperationSource.SERVER);
          this.currentServerState = applyOperation(merge, currentServerState);
          return merge;
        } else {
          Overwrite overwrite = getRandomOverwrite(OperationSource.SERVER);
          if (overwrite.getPath().getBack() != null
              && overwrite.getPath().getBack().isPriorityChildName()
              && this.currentServerState.getChild(overwrite.getPath().getParent()).isEmpty()) {
            // This is a case where we would overwrite a priority on an empty node which is an
            // illegal update
            return nextOperation();
          }
          this.currentServerState = applyOperation(overwrite, currentServerState);
          return overwrite;
        }
      }
    } else {
      if (random.nextDouble() < MERGE_PROBABILITY) {
        Merge merge = getRandomMerge(OperationSource.USER);
        WriteOp writeOp = new WriteOp(merge, currentWriteId++);
        outstandingWrites.add(writeOp);
        writeTree.addMerge(
            merge.getPath(), CompoundWrite.fromChildMerge(getMergeMap(merge)), writeOp.writeId);
        return merge;
      } else {
        Overwrite overwrite = getRandomOverwrite(OperationSource.USER);
        WriteOp writeOp = new WriteOp(overwrite, currentWriteId++);
        outstandingWrites.add(writeOp);
        writeTree.addOverwrite(overwrite.getPath(), overwrite.getSnapshot(), writeOp.writeId, true);
        return overwrite;
      }
    }
  }