This job view page is being replaced by Spyglass soon. Check out the new job view.
ResultFAILURE
Tests 0 failed / 0 succeeded
Started2019-04-18 17:49
Elapsed2m30s
Revision4d1e55498b430b74d7a58cf1eb8eac0dc6333a32
Refs 826

No Test Failures!


Error lines from build-log.txt

... skipping 37 lines ...
-      return kEmptyCode;
-    case Color::kBlack:
-      return kBlackCode;
-    case Color::kWhite:
-      return kWhiteCode;
-    default:
-      MG_LOG(FATAL) << "<" << static_cast<int>(color) << ">";
-      return "BAD";
-  }
-}
-
-}  // namespace minigo
-// Copyright 2018 Google LLC
... skipping 407 lines ...
-    std::unique_ptr<DualNet> dual_net;
-
-    std::vector<std::string> bigtable_spec =
-        absl::StrSplit(FLAGS_output_bigtable, ',');
-    bool use_bigtable = bigtable_spec.size() == 3;
-    if (!FLAGS_output_bigtable.empty() && !use_bigtable) {
-      MG_LOG(FATAL)
-          << "Bigtable output must be of the form: project,instance,table";
-      return;
-    }
-
-    Game game(black_model->name(), white_model->name(), game_options_);
-
... skipping 214 lines ...
-    history->push_back(&moves_[move - i]->stones);
-  }
-}
-
-bool Game::FindBleakestMove(int* move, float* q) const {
-  if (!game_over_) {
-    MG_LOG(ERROR) << "game isn't over";
-    return false;
-  }
-  if (options_.resign_enabled || moves_.empty()) {
-    return false;
-  }
-
... skipping 460 lines ...
-
-GtpClient::Response GtpClient::ReplaySgf(
-    const std::vector<std::unique_ptr<sgf::Node>>& trees) {
-  if (!trees.empty()) {
-    for (const auto& move : trees[0]->ExtractMainLine()) {
-      if (!player_->PlayMove(move.c)) {
-        MG_LOG(ERROR) << "couldn't play move " << move.c;
-        return Response::Error("cannot load file");
-      }
-    }
-  }
-  return Response::Ok();
-}
-
... skipping 28 lines ...
-  return response;
-}
-
-GtpClient::Response GtpClient::CheckArgsExact(size_t expected_num_args,
-                                              CmdArgs args) {
-  if (args.size() != expected_num_args) {
-    return Response::Error("expected ", expected_num_args, " args, got ",
-                           args.size(), " args: ", absl::StrJoin(args, " "));
-  }
-  return Response::Ok();
-}
-
-GtpClient::Response GtpClient::CheckArgsRange(size_t expected_min_args,
-                                              size_t expected_max_args,
-                                              CmdArgs args) {
-  if (args.size() < expected_min_args || args.size() > expected_max_args) {
-    return Response::Error("expected between ", expected_min_args, " and ",
-                           expected_max_args, " args, got ", args.size(),
-                           " args: ", absl::StrJoin(args, " "));
-  }
-  return Response::Ok();
-}
-
-GtpClient::Response GtpClient::DispatchCmd(const std::string& cmd,
-                                           CmdArgs args) {
-  auto it = cmd_handlers_.find(cmd);
-  if (it == cmd_handlers_.end()) {
-    return Response::Error("unknown command");
-  }
-  return it->second(args);
-}
-
-GtpClient::Response GtpClient::HandleBenchmark(CmdArgs args) {
-  // benchmark [readouts] [virtual_losses]
... skipping 6 lines ...
-  auto saved_options = player_->options();
-  auto temp_options = saved_options;
-
-  if (args.size() > 0) {
-    temp_options.seconds_per_move = 0;
-    if (!absl::SimpleAtoi(args[0], &temp_options.num_readouts)) {
-      return Response::Error("bad num_readouts");
-    }
-  }
-
-  if (args.size() == 2) {
-    if (!absl::SimpleAtoi(args[1], &temp_options.virtual_losses)) {
-      return Response::Error("bad virtual_losses");
-    }
-  }
-
-  player_->SetOptions(temp_options);
-  player_->SuggestMove();
-  player_->SetOptions(saved_options);
... skipping 6 lines ...
-  if (!response.ok) {
-    return response;
-  }
-
-  int x;
-  if (!absl::SimpleAtoi(args[0], &x) || x != kN) {
-    return Response::Error("unacceptable size");
-  }
-
-  return Response::Ok();
-}
-
-GtpClient::Response GtpClient::HandleClearBoard(CmdArgs args) {
... skipping 25 lines ...
-GtpClient::Response GtpClient::HandleGenmove(CmdArgs args) {
-  auto response = CheckArgsRange(0, 1, args);
-  if (!response.ok) {
-    return response;
-  }
-  if (player_->root()->game_over()) {
-    return Response::Error("game is over");
-  }
-
-  // TODO(tommadams): Handle out of turn moves.
-
-  Coord c = Coord::kInvalid;
-  if (options_.courtesy_pass && player_->root()->move == Coord::kPass) {
... skipping 28 lines ...
-  if (!response.ok) {
-    return response;
-  }
-
-  double x;
-  if (!absl::SimpleAtod(args[0], &x) || x != player_->game()->options().komi) {
-    return Response::Error("unacceptable komi");
-  }
-
-  return Response::Ok();
-}
-
-GtpClient::Response GtpClient::HandleListCommands(CmdArgs args) {
... skipping 16 lines ...
-  if (!response.ok) {
-    return response;
-  }
-
-  std::string contents;
-  if (!file::ReadFile(std::string(args[0]), &contents)) {
-    return Response::Error("cannot load file");
-  }
-
-  std::vector<std::unique_ptr<sgf::Node>> trees;
-  response = ParseSgf(contents, &trees);
-  if (!response.ok) {
-    return response;
... skipping 15 lines ...
-GtpClient::Response GtpClient::HandlePlay(CmdArgs args) {
-  auto response = CheckArgsExact(2, args);
-  if (!response.ok) {
-    return response;
-  }
-  if (player_->root()->game_over()) {
-    return Response::Error("game is over");
-  }
-
-  Color color;
-  if (std::tolower(args[0][0]) == 'b') {
-    color = Color::kBlack;
-  } else if (std::tolower(args[0][0]) == 'w') {
-    color = Color::kWhite;
-  } else {
-    MG_LOG(ERROR) << "expected b or w for player color, got " << args[0];
-    return Response::Error("illegal move");
-  }
-  if (color != player_->root()->position.to_play()) {
-    return Response::Error("out of turn moves are not yet supported");
-  }
-
-  Coord c = Coord::FromGtp(args[1], true);
-  if (c == Coord::kInvalid) {
-    MG_LOG(ERROR) << "expected GTP coord for move, got " << args[1];
-    return Response::Error("illegal move");
-  }
-
-  if (!player_->PlayMove(c)) {
-    return Response::Error("illegal move");
-  }
-
-  return Response::Ok();
-}
-
-GtpClient::Response GtpClient::HandlePonder(CmdArgs args) {
... skipping 20 lines ...
-  }
-
-  if (args[0] == "reads") {
-    // Enable pondering limited by number of reads.
-    int read_limit;
-    if (!absl::SimpleAtoi(args[1], &read_limit) || read_limit <= 0) {
-      return Response::Error("couldn't parse read limit");
-    }
-    options_.ponder_limit = read_limit;
-    ponder_type_ = PonderType::kReadLimited;
-    ponder_read_count_ = 0;
-    ponder_limit_reached_ = false;
-    return Response::Ok();
-  }
-
-  if (args[0] == "time") {
-    // Enable pondering limited by time.
-    float duration;
-    if (!absl::SimpleAtof(args[1], &duration) || duration <= 0) {
-      return Response::Error("couldn't parse time limit");
-    }
-    ponder_type_ = PonderType::kTimeLimited;
-    ponder_duration_ = absl::Seconds(duration);
-    ponder_time_limit_ = absl::Now() + ponder_duration_;
-    ponder_limit_reached_ = false;
-    return Response::Ok();
-  }
-
-  return Response::Error("unrecognized ponder mode");
-}
-
-GtpClient::Response GtpClient::HandleReadouts(CmdArgs args) {
-  auto response = CheckArgsExact(1, args);
-  if (!response.ok) {
-    return response;
-  }
-
-  int x;
-  if (!absl::SimpleAtoi(args[0], &x) || x <= 0) {
-    return Response::Error("couldn't parse ", args[0], " as an integer > 0");
-  } else {
-    auto options = player_->options();
-    options.num_readouts = x;
-    player_->SetOptions(options);
-  }
-
... skipping 13 lines ...
-  auto response = CheckArgsExact(0, args);
-  if (!response.ok) {
-    return response;
-  }
-
-  if (!player_->UndoMove()) {
-    return Response::Error("cannot undo");
-  }
-
-  return Response::Ok();
-}
-
-GtpClient::Response GtpClient::ParseSgf(
-    const std::string& sgf_str,
-    std::vector<std::unique_ptr<sgf::Node>>* trees) {
-  sgf::Ast ast;
-  if (!ast.Parse(sgf_str)) {
-    MG_LOG(ERROR) << "couldn't parse SGF";
-    return Response::Error("cannot load file");
-  }
-  if (!sgf::GetTrees(ast, trees)) {
-    return Response::Error("cannot load file");
-  }
-  return Response::Ok();
-}
-
-}  // namespace minigo
-
... skipping 87 lines ...
-
-  char c;
-  switch (level) {
-    case LogLevel::WARNING:
-      c = 'W';
-      break;
-    case LogLevel::ERROR:
-      c = 'E';
-      break;
-    case LogLevel::FATAL:
-      c = 'F';
-      break;
-    default:
-      c = 'U';
-      break;
-  }
... skipping 10 lines ...
-}
-
-LogStream::~LogStream() {
-  {
-    absl::MutexLock lock(mutex());
-    std::cerr << stream_.rdbuf() << '\n';
-    if (level_ == LogLevel::FATAL) {
-      DumpStackTrace(&std::cerr);
-    }
-    std::cerr << std::flush;
-  }
-  if (level_ == LogLevel::FATAL) {
-    exit(1);
-  }
-}
-
-CheckFailStream::CheckFailStream(const char* cond, const char* file, int line)
-    : impl_(file, line, LogLevel::FATAL) {
-  impl_ << "check failed: " << cond << '\n';
-}
-
-}  // namespace internal
-}  // namespace minigo
-// Copyright 2018 Google LLC
-//
... skipping 769 lines ...
-  root.stats->N = 100000;
-  for (int i = 0; i < kNumMoves; ++i) {
-    if (root.position.ClassifyMove(i) != Position::MoveType::kIllegal) {
-      root.edges[i].N = 10000;
-    }
-  }
-  // this should not throw an error...
-  auto* leaf = root.SelectLeaf();
-  // the returned leaf should not be the illegal move
-  EXPECT_NE(1, leaf->move);
-
-  // and even after injecting noise, we should still not select an illegal
-  // move
... skipping 489 lines ...
-  }
-  return absl::StrJoin(parts, ", ");
-}
-
-bool MctsPlayer::PlayMove(Coord c) {
-  if (root_->game_over()) {
-    MG_LOG(ERROR) << "can't play move " << c << ", game is over";
-    return false;
-  }
-
-  // Handle resignations.
-  if (c == Coord::kResign) {
-    game_->SetGameOverBecauseOfResign(OtherColor(root_->position.to_play()));
-    return true;
-  }
-
-  if (!root_->position.legal_move(c)) {
-    MG_LOG(ERROR) << "Move " << c << " is illegal";
-    // We're probably about to crash. Dump the player's options and the moves
-    // that got us to this point.
-    MG_LOG(ERROR) << "MctsPlayer options: " << options_;
-    MG_LOG(ERROR) << "Game options: " << game_->options();
-    for (int i = 0; i < game_->num_moves(); ++i) {
-      const auto* move = game_->GetMove(i);
-      MG_LOG(ERROR) << move->color << "  " << move->c;
-    }
-    return false;
-  }
-
-  UpdateGame(c);
-
... skipping 453 lines ...
-  auto player = CreateAlmostDonePlayer();
-  auto* root = player->root();
-
-  // Initialize the tree so that the root node has populated children.
-  player->TreeSearch(1);
-  // Virtual losses should enable multiple searches to happen simultaneously
-  // without throwing an error...
-  for (int i = 0; i < 5; ++i) {
-    player->TreeSearch(5);
-  }
-
-  // Search should converge on D9 as only winning move.
-  auto best_move = ArgMax(root->edges, MctsNode::CmpN);
... skipping 413 lines ...
-  if (!response.ok) {
-    return response;
-  }
-
-  int x;
-  if (!absl::SimpleAtoi(args[0], &x) || x < 0) {
-    return Response::Error("couldn't parse ", args[0], " as an integer >= 0");
-  }
-  report_search_interval_ = absl::Milliseconds(x);
-
-  return Response::Ok();
-}
-
-GtpClient::Response MiniguiGtpClient::HandleSelectPosition(CmdArgs args) {
-  auto response = CheckArgsExact(1, args);
-  if (!response.ok) {
-    return response;
-  }
-
-  if (!variation_tree_->SelectNode(std::string(args[0]))) {
-    return Response::Error("unknown position id");
-  }
-
-  player_->NewGame();
-  for (auto c : variation_tree_->current_node()->GetVariation()) {
-    MG_CHECK(player_->PlayMove(c));
-  }
... skipping 3 lines ...
-  return Response::Ok();
-}
-
-GtpClient::Response MiniguiGtpClient::HandleWinrateEvals(CmdArgs args) {
-  int num_reads;
-  if (!absl::SimpleAtoi(args[1], &num_reads) || num_reads < 0) {
-    return Response::Error("invalid num_reads");
-  }
-  win_rate_evaluator_->SetNumEvalReads(num_reads);
-  RefreshPendingWinRateEvals();
-  return Response::Ok();
-}
-
... skipping 6 lines ...
-        if (node.move.color != player_->root()->position.to_play()) {
-          // The move color is different than expected. Play a pass move to flip
-          // the colors.
-          if (player_->root()->move == Coord::kPass) {
-            auto expected = ColorToCode(player_->root()->position.to_play());
-            auto actual = node.move.ToSgf();
-            MG_LOG(ERROR) << "expected move by " << expected << ", got "
-                          << actual
-                          << " but can't play an intermediate pass because the"
-                          << " previous move was also a pass";
-            return Response::Error("cannot load file");
-          }
-          MG_LOG(WARNING) << "Inserting pass move";
-          MG_CHECK(player_->PlayMove(Coord::kPass));
-          variation_tree_->PlayMove(Coord::kPass);
-          ReportRootPosition();
-        }
-
-        if (!player_->PlayMove(node.move.c)) {
-          MG_LOG(ERROR) << "error playing " << node.move.ToSgf();
-          return Response::Error("cannot load file");
-        }
-        variation_tree_->PlayMove(node.move.c);
-        if (!node.comment.empty()) {
-          variation_tree_->current_node()->comment = node.comment;
-        }
-        ReportRootPosition();
... skipping 2053 lines ...
-
-    ThreadOptions thread_options;
-    std::vector<std::string> bigtable_spec =
-        absl::StrSplit(FLAGS_output_bigtable, ',');
-    bool use_bigtable = bigtable_spec.size() == 3;
-    if (!FLAGS_output_bigtable.empty() && !use_bigtable) {
-      MG_LOG(FATAL)
-          << "Bigtable output must be of the form: project,instance,table";
-      return;
-    }
-
-    for (;;) {
-      std::unique_ptr<Game> game;
... skipping 239 lines ...
-namespace sgf {
-
-namespace {
-
-class Parser {
- public:
-  Parser(absl::string_view contents, std::string* error)
-      : original_contents_(contents), contents_(contents), error_(error) {}
-
-  bool Parse(std::vector<Ast::Tree>* trees) {
-    *error_ = "";
-    while (SkipWhitespace()) {
-      trees->emplace_back();
-      if (!ParseTree(&trees->back())) {
... skipping 15 lines ...
-    if (!ParseSequence(tree)) {
-      return false;
-    }
-
-    for (;;) {
-      if (!SkipWhitespace()) {
-        return Error("reached EOF when parsing tree");
-      }
-      if (peek() == '(') {
-        tree->children.emplace_back();
-        if (!ParseTree(&tree->children.back())) {
-          return false;
-        }
... skipping 2 lines ...
-      }
-    }
-  }
-
-  bool ParseSequence(Ast::Tree* tree) {
-    if (!SkipWhitespace()) {
-      return Error("reached EOF when parsing sequence");
-    }
-    for (;;) {
-      if (peek() != ';') {
-        // All valid trees must contain at least one node.
-        if (tree->nodes.empty()) {
-          return Error("tree has no nodes");
-        }
-        return true;
-      }
-      Read(';');
-      tree->nodes.emplace_back();
-      if (!ParseNode(&tree->nodes.back())) {
... skipping 2 lines ...
-    }
-  }
-
-  bool ParseNode(Ast::Node* node) {
-    for (;;) {
-      if (!SkipWhitespace()) {
-        return Error("reached EOF when parsing node");
-      }
-      if (!absl::ascii_isupper(peek())) {
-        return true;
-      }
-      node->properties.emplace_back();
-      if (!ParseProperty(&node->properties.back())) {
... skipping 4 lines ...
-
-  bool ParseProperty(Ast::Property* prop) {
-    if (!ReadTo('[', &prop->id)) {
-      return false;
-    }
-    if (prop->id.empty()) {
-      return Error("property has an empty ID");
-    }
-    bool read_value = false;
-    for (;;) {
-      if (!SkipWhitespace()) {
-        return Error("reached EOF when parsing property ", prop->id);
-      }
-      if (peek() != '[') {
-        if (!read_value) {
-          return Error("property ", prop->id, " has no values");
-        }
-        return true;
-      }
-      Read('[');
-      read_value = true;
-      std::string value;
... skipping 4 lines ...
-      Read(']');
-    }
-  }
-
-  bool Read(char c) {
-    if (done()) {
-      return Error("expected '", absl::string_view(&c, 1), "', got EOF");
-    }
-    if (contents_[0] != c) {
-      return Error("expected '", absl::string_view(&c, 1), "', got '",
-                   contents_.substr(0, 1), "'");
-    }
-    contents_ = contents_.substr(1);
-    return true;
-  }
-
... skipping 16 lines ...
-        return true;
-      }
-
-      absl::StrAppend(result, absl::string_view(&x, 1));
-      read_escape = false;
-    }
-    return Error("reached EOF before finding '", absl::string_view(&c, 1), "'");
-  }
-
-  // Skip over whitespace.
-  // Updates contents_ and returns true if there are non-whitespace characters
-  // remaining. Leaves contents_ alone and returns false if only whitespace
-  // characters remain.
-  bool SkipWhitespace() {
-    contents_ = absl::StripLeadingAsciiWhitespace(contents_);
-    return !contents_.empty();
-  }
-
-  template <typename... Args>
-  bool Error(Args&&... args) {
-    // Find the line & column number the error occured at.
-    int line = 1;
-    int col = 1;
-    for (auto* c = original_contents_.data(); c != contents_.data(); ++c) {
-      if (*c == '\n') {
-        ++line;
-        col = 1;
-      } else {
-        ++col;
-      }
-    }
-    *error_ = absl::StrCat("ERROR at line:", line, " col:", col, ": ", args...);
-    return false;
-  }
-
-  absl::string_view original_contents_;
-  absl::string_view contents_;
-  std::string* error_;
... skipping 20 lines ...
-                      << " because property " << prop->ToString()
-                      << " has no values";
-      continue;
-    }
-    move.c = Coord::FromSgf(prop->values[0], true);
-    if (move.c == Coord::kInvalid) {
-      MG_LOG(ERROR) << "Can't parse node " << node.ToString() << ": \""
-                    << prop->values[0] << "\" isn't a valid SGF coord";
-      return false;
-    }
-
-    // Parse comment.
-    std::string comment;
... skipping 158 lines ...
-class AstTest : public ::testing::Test {
- protected:
-  Ast ast_;
-};
-
-TEST_F(AstTest, NoTrees) {
-  EXPECT_TRUE(ast_.Parse("")) << ast_.error();
-  EXPECT_TRUE(ast_.Parse(" \n ")) << ast_.error();
-}
-
-TEST_F(AstTest, BadTree) { EXPECT_FALSE(ast_.Parse("   \n  x")); }
-
-TEST_F(AstTest, EmptyTree) { EXPECT_FALSE(ast_.Parse("()")); }
-
-TEST_F(AstTest, EmptyNode) {
-  EXPECT_TRUE(ast_.Parse("(;)")) << ast_.error();
-  ASSERT_EQ(1, ast_.trees().size());
-  EXPECT_EQ(1, ast_.trees()[0].nodes.size());
-  EXPECT_EQ(0, ast_.trees()[0].nodes[0].properties.size());
-  EXPECT_EQ(0, ast_.trees()[0].children.size());
-  EXPECT_EQ("(;)", ast_.trees()[0].ToString());
-}
-
-TEST_F(AstTest, MultipleEmptyNodes) {
-  EXPECT_TRUE(ast_.Parse("(;;;)")) << ast_.error();
-  ASSERT_EQ(1, ast_.trees().size());
-  EXPECT_EQ(3, ast_.trees()[0].nodes.size());
-  EXPECT_EQ("(;\n;\n;)", ast_.trees()[0].ToString());
-}
-
-TEST_F(AstTest, OneNodeTree) {
-  EXPECT_TRUE(ast_.Parse("(;A[1][hmm])")) << ast_.error();
-  ASSERT_EQ(1, ast_.trees().size());
-  EXPECT_EQ("(;A[1][hmm])", ast_.trees()[0].ToString());
-}
-
-TEST_F(AstTest, PropertyIdIsMissing) { EXPECT_FALSE(ast_.Parse("(;[])")); }
-
-TEST_F(AstTest, PropertyIdIsNotUpper) { EXPECT_FALSE(ast_.Parse("(;a[])")); }
-
-TEST_F(AstTest, PropertyHasOneEmptyValue) {
-  EXPECT_TRUE(ast_.Parse("(;A[])")) << ast_.error();
-}
-
-TEST_F(AstTest, PropertyHasMultipleEmptyValues) {
-  EXPECT_TRUE(ast_.Parse("(;A[][][])")) << ast_.error();
-  ASSERT_EQ(1, ast_.trees().size());
-  EXPECT_EQ(1, ast_.trees()[0].nodes.size());
-  EXPECT_EQ(1, ast_.trees()[0].nodes[0].properties.size());
-  EXPECT_EQ("A", ast_.trees()[0].nodes[0].properties[0].id);
-  EXPECT_EQ(3, ast_.trees()[0].nodes[0].properties[0].values.size());
-  EXPECT_EQ("(;A[][][])", ast_.trees()[0].ToString());
-}
-
-TEST_F(AstTest, NestedTrees) {
-  EXPECT_TRUE(ast_.Parse("(; (;A[b][c];D[]) (;) (;E[f];G[] (;H[i])))"))
-      << ast_.error();
-  ASSERT_EQ(1, ast_.trees().size());
-  EXPECT_EQ(R"((;
-(;A[b][c]
-;D[])
-(;)
-(;E[f]
-;G[]
-(;H[i]))))",
-            ast_.trees()[0].ToString());
-}
-
-TEST_F(AstTest, MultipleTrees) {
-  EXPECT_TRUE(ast_.Parse("(;A[])(;B[c]) (  ;D[e][f])")) << ast_.error();
-  ASSERT_EQ(3, ast_.trees().size());
-  EXPECT_EQ("(;A[])", ast_.trees()[0].ToString());
-  EXPECT_EQ("(;B[c])", ast_.trees()[1].ToString());
-  EXPECT_EQ("(;D[e][f])", ast_.trees()[2].ToString());
-}
-
... skipping 50 lines ...
-}
-
-TEST(SgfTest, InvalidCoord) {
-  std::string sgf = "(;FF[4](;B[xx]))\n";
-
-  Ast ast;
-  ASSERT_TRUE(ast.Parse(sgf)) << ast.error();
-  std::vector<std::unique_ptr<sgf::Node>> trees;
-  EXPECT_FALSE(GetTrees(ast, &trees));
-}
-
-TEST(SgfTest, GetMainLineMoves) {
-  /*
... skipping 13 lines ...
-      {Color::kBlack, Coord::FromSgf("aa")},
-      {Color::kWhite, Coord::FromSgf("ab")},
-      {Color::kBlack, Coord::FromSgf("ac")},
-  };
-
-  Ast ast;
-  ASSERT_TRUE(ast.Parse(sgf)) << ast.error();
-
-  std::vector<std::unique_ptr<sgf::Node>> trees;
-  ASSERT_TRUE(GetTrees(ast, &trees));
-  ASSERT_EQ(2, trees.size());
-  auto actual_main_line = trees[0]->ExtractMainLine();
-  EXPECT_THAT(actual_main_line, ::testing::ContainerEq(expected_main_line));
-}
-
-TEST(SgfTest, CommentEscaping) {
-  // Fragment of an SGF that contains escaped characters.
-  std::string sgf = "(;FF[4];C[test [?\\]: comment]B[aa];W[bb]C[\\]])";
-
-  Ast ast;
-  EXPECT_TRUE(ast.Parse(sgf)) << ast.error();
-
-  std::vector<std::unique_ptr<sgf::Node>> trees;
-  ASSERT_TRUE(GetTrees(ast, &trees));
-  ASSERT_EQ(1, trees.size());
-
-  EXPECT_EQ("aa", trees[0]->move.c.ToSgf());
... skipping 791 lines ...
-  for (auto const& cell : row.cells()) {
-    if (cell.family_name() == "metadata" &&
-        cell.column_qualifier() == counter_name) {
-      return cell.value_as<bigendian64_t>().get();
-    }
-  }
-  MG_LOG(FATAL) << "Failed to increment table_state=metadata:" << counter_name;
-  return 0;
-}
-
-void PortGamesToBigtable(const std::string& gcp_project_name,
-                         const std::string& instance_name,
-                         const std::string& table_name,
... skipping 9 lines ...
-  Table table(
-      CreateDefaultDataClient(gcp_project_name, instance_name, client_options),
-      table_name);
-
-  if (game_counter < 0) {
-    if (paths.size() != 1) {
-      MG_LOG(FATAL) << "Atomic game updates require batch size of 1 game";
-      return;
-    }
-    MG_LOG(FATAL) << "Have not yet implemented atomic game counter update.";
-    return;
-  }
-
-  BulkMutation game_batch;
-  auto start_time = absl::Now();
-  int changes = 0;
... skipping 70 lines ...
-namespace minigo {
-namespace tf_utils {
-
-void WriteGameExamples(const std::string& gcp_project_name,
-                       const std::string& instance_name,
-                       const std::string& table_name, const Game& game) {
-  MG_LOG(FATAL)
-      << "Can't write TensorFlow examples to Bigtable without Bigtable "
-         "support enabled. "
-         "Please recompile, passing --define=bt=1 to bazel build.";
-}
-
-void WriteEvalRecord(const std::string& gcp_project_name,
-                     const std::string& instance_name,
-                     const std::string& table_name, const Game& game,
-                     const std::string& sgf_name, const std::string& tag) {
-  MG_LOG(FATAL) << "Can't write eval record to Bigtable without Bigtable "
-                   "support enabled. "
-                   "Please recompile, passing --define=bt=1 to bazel build.";
-}
-
-uint64_t IncrementGameCounter(const std::string& gcp_project_name,
-                              const std::string& instance_name,
-                              const std::string& table_name,
-                              const std::string& counter_name, size_t delta) {
-  MG_LOG(FATAL) << "Can't increment a Bigtable game counter without Bigtable "
-                   "support enabled. "
-                   "Please recompile, passing --define=bt=1 to bazel build.";
-  return 0;
-}
-
-void PortGamesToBigtable(const std::string& gcp_project_name,
-                         const std::string& instance_name,
-                         const std::string& table_name,
-                         const std::vector<std::string>& paths,
-                         int64_t game_counter) {
-  MG_LOG(FATAL)
-      << "Can't port TFRecord ZLIB files to Bigtable without Bigtable "
-         "support enabled. "
-         "Please recompile, passing --define=bt=1 to bazel build.";
-}
-
-}  // namespace tf_utils
... skipping 141 lines ...
-
-namespace minigo {
-namespace tf_utils {
-
-void WriteGameExamples(const std::string& output_dir,
-                       const std::string& output_name, const Game& game) {
-  MG_LOG(FATAL)
-      << "Can't write TensorFlow examples without TensorFlow support enabled. "
-         "Please recompile, passing --define=tf=1 to bazel build.";
-}
-
-}  // namespace tf_utils
-}  // namespace minigo
... skipping 56 lines ...
-
-void wait_for_children(std::set<int>* pids, size_t maximum_children) {
-  while (pids->size() > maximum_children) {
-    int status;
-    int child_pid = wait(&status);
-    if (status != 0) {
-      MG_LOG(FATAL) << "Child pid " << child_pid << " did not succeed";
-    }
-    auto where = pids->find(child_pid);
-    if (where == pids->end()) {
-      MG_LOG(FATAL) << "Child pid " << child_pid << " not found";
-    } else {
-      pids->erase(where);
-    }
-  }
-}
-
-int main(int argc, char* argv[]) {
-  minigo::Init(&argc, &argv);
-
-  std::vector<std::string> bigtable_spec =
-      absl::StrSplit(FLAGS_output_bigtable, ',');
-  bool use_bigtable = bigtable_spec.size() == 3;
-  if (!FLAGS_output_bigtable.empty() && !use_bigtable) {
-    MG_LOG(FATAL)
-        << "Bigtable output must be of the form: project,instance,table";
-    return 1;
-  }
-
-  std::deque<std::string> paths(argv + 1, argv + argc);
-  if (!paths.empty()) {
... skipping 369 lines ...
-      for (int i = 0; i < kNumMoves; ++i) {
-        if (policy[0][i] != policy[replica][i]) {
-          Log() << absl::StreamFormat("policy[0][%d] == %f\n",
-                                      i, policy[0][i]);
-          Log() << absl::StreamFormat("policy[%d][%d] == %f\n",
-                                      replica, i, policy[replica][i]);
-          LOG(FATAL) << ":(";
-        }
-        if (value[0] != value[replica]) {
-          Log() << absl::StreamFormat("value[0] == %f\n", value[0]);
-          Log() << absl::StreamFormat("value[%d] == %f\n",
-                                      replica, value[replica]);
-          LOG(FATAL) << ":(";
-        }
-      }
-    }
-
-    // Log the output of the first replica (since the other replica outputs
-    // all match the first).
... skipping 728 lines ...
-      response.str = std::move(str);
-      response.ok = true;
-      return response;
-    }
-
-    template <typename... Args>
-    static Response Error(const Args&... args) {
-      Response response;
-      response.str = absl::StrCat(args...);
-      response.ok = false;
-      return response;
-    }
-
... skipping 285 lines ...
-namespace minigo {
-namespace internal {
-
-enum class LogLevel {
-  INFO,
-  WARNING,
-  ERROR,
-  FATAL,
-};
-
-// A simple thread-safe logging stream that replaces logging directly to
-// stderr, which is not thread-safe.
-// All logging is written to stderr.
-// For log levels other than INFO, the line is prefixed with the log level and
... skipping 1190 lines ...
-    std::vector<Tree> children;
-  };
-
-  // Parses the SGF file.
-  MG_WARN_UNUSED_RESULT bool Parse(std::string contents);
-
-  // Returns a non-empty string containing error information if the most recent
-  // call to Parse returned false.
-  const std::string& error() const { return error_; }
-
-  const std::vector<Tree>& trees() const { return trees_; }
-
- private:
-  std::string error_;
-  std::vector<Tree> trees_;
... skipping 178 lines ...
-      return kFlipRot90;
-    case kFlipRot180:
-      return kFlipRot180;
-    case kFlipRot270:
-      return kFlipRot270;
-    default:
-      MG_LOG(FATAL) << static_cast<int>(sym);
-      return kNumSymmetries;
-  }
-}
-
-template <int N, int num_channels, typename SrcIt, typename DstIt>
-inline void Identity(SrcIt src, DstIt dst) {
... skipping 117 lines ...
-      FlipRot180<N, num_channels>(src, dst);
-      break;
-    case Symmetry::kFlipRot270:
-      FlipRot270<N, num_channels>(src, dst);
-      break;
-    default:
-      MG_LOG(FATAL) << static_cast<int>(sym);
-      break;
-  }
-}
-
-template <int N, int num_channels, typename T>
-class NchwOutputIterator {
... skipping 1377 lines ...
-  if (engine == "trt") {
-    MG_CHECK(arg_str.empty());
-    return absl::make_unique<TrtDualNetFactory>();
-  }
-#endif  // MG_ENABLE_TRT_DUAL_NET
-
-  MG_LOG(FATAL) << "Unrecognized inference engine \"" << engine << "\"";
-  return nullptr;
-}
-
-}  // namespace minigo
-// Copyright 2018 Google LLC
-//
... skipping 452 lines ...
-      return RunMany(features, outputs, input_->data.f, policy_->data.f,
-                     value_->data.f);
-    case kTfLiteUInt8:
-      return RunMany(features, outputs, input_->data.uint8, policy_->data.uint8,
-                     value_->data.uint8);
-    default:
-      MG_LOG(FATAL) << "Unsupported input type";
-  }
-}
-
-template <typename T, typename S>
-T Convert(const TfLiteQuantizationParams&, const S& x) {
-  return static_cast<T>(x);
... skipping 167 lines ...
-    std::string* basename_pattern) {
-  auto pair = file::SplitPath(pattern);
-
-  *directory = std::string(pair.first);
-  if (directory->find('%') != std::string::npos ||
-      directory->find('*') != std::string::npos) {
-    MG_LOG(ERROR) << "invalid pattern \"" << pattern
-                  << "\": directory part must not contain '*' or '%'";
-    return false;
-  }
-  if (directory->empty()) {
-    MG_LOG(ERROR) << "directory not be empty";
-    return false;
-  }
-
-  *basename_pattern = std::string(pair.second);
-  auto it = basename_pattern->find('%');
-  if (it == std::string::npos || basename_pattern->find("%d") != it ||
-      basename_pattern->rfind("%d") != it) {
-    MG_LOG(ERROR) << "invalid pattern \"" << pattern
-                  << "\": basename must contain "
-                  << " exactly one \"%d\" and no other matchers";
-    return false;
-  }
-  return true;
-}
... skipping 819 lines ...
-class TrtDualNet : public DualNet {
-  class TrtLogger : public nvinfer1::ILogger {
-   public:
-    void log(nvinfer1::ILogger::Severity severity, const char* msg) override {
-      switch (severity) {
-        case Severity::kINTERNAL_ERROR:
-          MG_LOG(ERROR) << "TensorRT internal error: " << msg;
-          break;
-        case Severity::kERROR:
-          MG_LOG(ERROR) << "TensorRT error: " << msg;
-          break;
-        case Severity::kWARNING:
-          MG_LOG(WARNING) << "TensorRT warning: " << msg;
-          break;
-        default:
-          break;
... skipping 154 lines ...
-          inference.notification->Notify();
-        }
-      }
-    };
-
-    for (auto& pair : pairs) {
-      MG_CHECK(pair.second) << "Failed to deserialize TensorRT engine.";
-      engines_.push_back(pair.second);
-      worker_threads_.emplace_back(functor, pair);
-      worker_threads_.emplace_back(functor, pair);
-    }
-    blob->destroy();
-  }
... skipping 1210 lines ...
-
-bool WriteFile(std::string path, absl::string_view contents) {
-  path = NormalizeSlashes(path);
-
-  FILE* f = fopen(path.c_str(), "wb");
-  if (f == nullptr) {
-    MG_LOG(ERROR) << "error opening " << path << " for write";
-    return false;
-  }
-
-  bool ok = true;
-  if (!contents.empty()) {
-    ok = fwrite(contents.data(), contents.size(), 1, f) == 1;
-    if (!ok) {
-      MG_LOG(ERROR) << "error writing " << path;
-    }
-  }
-  fclose(f);
-  return ok;
-}
-
-bool ReadFile(std::string path, std::string* contents) {
-  path = NormalizeSlashes(path);
-
-  FILE* f = fopen(path.c_str(), "rb");
-  if (f == nullptr) {
-    MG_LOG(ERROR) << "error opening " << path << " for read";
-    return false;
-  }
-  fseek(f, 0, SEEK_END);
-  contents->resize(ftell(f));
-  fseek(f, 0, SEEK_SET);
-  bool ok = fread(&(*contents)[0], contents->size(), 1, f) == 1;
-  if (!ok) {
-    MG_LOG(ERROR) << "error reading " << path;
-  }
-  fclose(f);
-  return ok;
-}
-
-bool GetModTime(std::string path, uint64_t* mtime_usec) {
-  path = NormalizeSlashes(path);
-
-  struct stat s;
-  int result = stat(path.c_str(), &s);
-  if (result != 0) {
-    MG_LOG(ERROR) << "error statting " << path << ": " << result;
-    return false;
-  }
-  *mtime_usec = static_cast<uint64_t>(s.st_mtime) * 1000 * 1000;
-  return true;
-}
-
-bool ListDir(std::string directory, std::vector<std::string>* files) {
-  directory = NormalizeSlashes(directory);
-
-  DIR* dirp = opendir(directory.c_str());
-  if (dirp == nullptr) {
-    MG_LOG(ERROR) << "could not open directory " << directory;
-    return false;
-  }
-  files->clear();
-  while (dirent* dp = readdir(dirp)) {
-    absl::string_view p(dp->d_name);
-    if (p == "." || p == "..") {
... skipping 46 lines ...
-
-TEST(UtilsTest, ReadAndWriteFile) {
-  // Recursively create a directory using both forward and back slashes.
-  auto dir = FullPath("foo/bar\\read_write");
-  ASSERT_TRUE(RecursivelyCreateDir(dir));
-
-  // Attempting to create an already existing directory shouldn't fail.
-  ASSERT_TRUE(RecursivelyCreateDir(dir));
-
-  // Write to a file under the new directory.
-  auto path = JoinPath(dir, "test.txt");
-  std::string expected_contents = "this is a test";
-  ASSERT_TRUE(WriteFile(path, expected_contents));
... skipping 35 lines ...
-  ASSERT_TRUE(WriteFile(JoinPath(dir, "c"), ""));
-
-  // List the directory.
-  std::vector<std::string> files;
-  ASSERT_TRUE(ListDir(dir, &files));
-
-  // The order of the returned list is undefined.
-  EXPECT_THAT(files, ::testing::UnorderedElementsAreArray({"a", "b", "c"}));
-}
-
-}  // namespace
-}  // namespace file
-}  // namespace minigo
... skipping 37 lines ...
-    return true;
-  }
-
-  auto* env = tensorflow::Env::Default();
-  status = env->RecursivelyCreateDir(path);
-  if (!status.ok()) {
-    MG_LOG(ERROR) << "error creating " << path << ": " << status;
-    return false;
-  }
-
-  return true;
-}
-
... skipping 3 lines ...
-  tensorflow::Status status;
-  auto* env = tensorflow::Env::Default();
-
-  std::unique_ptr<tensorflow::WritableFile> file;
-  status = env->NewWritableFile(path, &file);
-  if (!status.ok()) {
-    MG_LOG(ERROR) << "error opening " << path << " for write: " << status;
-    return false;
-  }
-
-  // *sigh* absl::string_view doesn't automatically convert to
-  // tensorflow::StringPiece even though I'm pretty sure they're exactly the
-  // same.
-  if (!contents.empty()) {
-    status = file->Append({contents.data(), contents.size()});
-    if (!status.ok()) {
-      MG_LOG(ERROR) << "error writing to " << path << ": " << status;
-      return false;
-    }
-  }
-
-  status = file->Close();
-  if (!status.ok()) {
-    MG_LOG(ERROR) << "error closing " << path << ": " << status;
-    return false;
-  }
-  return true;
-}
-
-bool ReadFile(std::string path, std::string* contents) {
... skipping 2 lines ...
-  tensorflow::Status status;
-  auto* env = tensorflow::Env::Default();
-
-  tensorflow::uint64 size;
-  status = env->GetFileSize(path, &size);
-  if (!status.ok()) {
-    MG_LOG(ERROR) << "error getting size of " << path << ": " << status;
-    return false;
-  }
-
-  std::unique_ptr<tensorflow::RandomAccessFile> file;
-  status = env->NewRandomAccessFile(path, &file);
-  if (!status.ok()) {
-    MG_LOG(ERROR) << "error opening " << path << " for read: " << status;
-    return false;
-  }
-
-  contents->resize(size);
-  tensorflow::StringPiece s;
-  status = file->Read(0u, size, &s, &(*contents)[0]);
-  if (!status.ok()) {
-    MG_LOG(ERROR) << "error reading " << path << ": " << status;
-    return false;
-  }
-  contents->resize(s.size());
-
-  return true;
-}
... skipping 4 lines ...
-  tensorflow::Status status;
-  auto* env = tensorflow::Env::Default();
-  tensorflow::FileStatistics stat;
-
-  status = env->Stat(path, &stat);
-  if (!status.ok()) {
-    MG_LOG(ERROR) << "error statting " << path << ": " << status;
-    return false;
-  }
-
-  *mtime_usec = static_cast<uint64_t>(stat.mtime_nsec / 1000);
-  return true;
-}
... skipping 3 lines ...
-
-  tensorflow::Status status;
-  auto* env = tensorflow::Env::Default();
-
-  status = env->GetChildren(directory, files);
-  if (!status.ok()) {
-    MG_LOG(ERROR) << "error getting " << directory << " content: " << status;
-    return false;
-  }
-
-  return true;
-}
-
... skipping 68 lines ...
-
-bool WriteFile(std::string path, absl::string_view contents) {
-  path = NormalizeSlashes(path);
-
-  FILE* f = fopen(path.c_str(), "wb");
-  if (f == nullptr) {
-    MG_LOG(ERROR) << "error opening " << path << " for write";
-    return false;
-  }
-  bool ok = true;
-  if (!contents.empty()) {
-    ok = fwrite(contents.data(), contents.size(), 1, f) == 1;
-    if (!ok) {
-      MG_LOG(ERROR) << "error writing " << path;
-    }
-  }
-  fclose(f);
-  return ok;
-}
-
-bool ReadFile(std::string path, std::string* contents) {
-  path = NormalizeSlashes(path);
-
-  FILE* f = fopen(path.c_str(), "rb");
-  if (f == nullptr) {
-    MG_LOG(ERROR) << "error opening " << path << " for read";
-    return false;
-  }
-  fseek(f, 0, SEEK_END);
-  contents->resize(ftell(f));
-  fseek(f, 0, SEEK_SET);
-  bool ok = fread(&(*contents)[0], contents->size(), 1, f) == 1;
-  if (!ok) {
-    MG_LOG(ERROR) << "error reading " << path;
-  }
-  fclose(f);
-  return ok;
-}
-
-bool GetModTime(std::string path, uint64_t* mtime_usec) {
... skipping 233 lines ...
   (cond)               \
   ^
./cc/algorithm.h:43:3: note: in expansion of macro 'MG_CHECK'
   MG_CHECK(!container.empty());
   ^
[199 / 253] 1 / 8 tests; Compiling cc/puzzle.cc; 4s processwrapper-sandbox ... (8 actions running)
ERROR: /home/prow/go/src/github.com/tensorflow/minigo/cc/BUILD:413:1: C++ compilation of rule '//cc:mcts_player_test' failed (Exit 1)

cc/mcts_player_test.cc:74:21: error: no members matching 'minigo::MctsPlayer::TreePath' in 'class minigo::MctsPlayer'
   using MctsPlayer::TreePath;
                     ^
cc/mcts_player_test.cc: In member function 'virtual void minigo::{anonymous}::MctsPlayerTest_SymmetriesTest_Test::TestBody()':
cc/mcts_player_test.cc:501:3: error: 'TreePath' is not a member of 'minigo::{anonymous}::TestablePlayer'
   TestablePlayer::TreePath path(root, root);
   ^
cc/mcts_player_test.cc:503:26: error: 'path' was not declared in this scope
   player.ProcessLeaves({&path, 1}, true);
                          ^
cc/mcts_player_test.cc:503:40: error: no matching function for call to 'minigo::{anonymous}::TestablePlayer::ProcessLeaves(<brace-enclosed initializer list>, bool)'
   player.ProcessLeaves({&path, 1}, true);
                                        ^
In file included from cc/mcts_player_test.cc:15:0:
./cc/mcts_player.h:161:8: note: candidate: void minigo::MctsPlayer::ProcessLeaves(const std::vector<minigo::MctsNode*>&, bool)
   void ProcessLeaves(const std::vector<MctsNode*>& leaves,
        ^
./cc/mcts_player.h:161:8: note:   no known conversion for argument 1 from '<brace-enclosed initializer list>' to 'const std::vector<minigo::MctsNode*>&'
cc/mcts_player_test.cc:528:42: error: no matching function for call to 'minigo::{anonymous}::TestablePlayer::ProcessLeaves(<brace-enclosed initializer list>, bool)'
     player.ProcessLeaves({&path, 1}, true);
                                          ^
In file included from cc/mcts_player_test.cc:15:0:
./cc/mcts_player.h:161:8: note: candidate: void minigo::MctsPlayer::ProcessLeaves(const std::vector<minigo::MctsNode*>&, bool)
   void ProcessLeaves(const std::vector<MctsNode*>& leaves,
        ^
... skipping 8 lines ...
   ^
./cc/algorithm.h:35:3: note: in expansion of macro 'MG_CHECK'
   MG_CHECK(!container.empty());
   ^
INFO: Elapsed time: 79.481s, Critical Path: 10.65s
INFO: 116 processes: 116 processwrapper-sandbox.
FAILED: Build did NOT complete successfully

//cc:coord_test                                                       NO STATUS
//cc:mcts_node_test                                                   NO STATUS
//cc:position_test                                                    NO STATUS
//cc:random_test                                                      NO STATUS
//cc:symmetries_test                                                  NO STATUS
//cc:thread_safe_queue_test                                           NO STATUS
//cc:sgf_test                                                            PASSED in 1.8s

Executed 1 out of 8 tests: 1 test passes, 1 fails to build and 6 were skipped.
FAILED: Build did NOT complete successfully

--------------------------------------
The tests did not pass successfully!