proxygen
testing::internal::edit_distance Namespace Reference

Enumerations

enum  EditType {
  kMatch, kAdd, kRemove, kReplace,
  kMatch, kAdd, kRemove, kReplace,
  kMatch, kAdd, kRemove, kReplace
}
 
enum  EditType {
  kMatch, kAdd, kRemove, kReplace,
  kMatch, kAdd, kRemove, kReplace,
  kMatch, kAdd, kRemove, kReplace
}
 
enum  EditType {
  kMatch, kAdd, kRemove, kReplace,
  kMatch, kAdd, kRemove, kReplace,
  kMatch, kAdd, kRemove, kReplace
}
 

Functions

GTEST_API_ std::vector< EditTypeCalculateOptimalEdits (const std::vector< size_t > &left, const std::vector< size_t > &right)
 
GTEST_API_ std::vector< EditTypeCalculateOptimalEdits (const std::vector< std::string > &left, const std::vector< std::string > &right)
 
GTEST_API_ std::string CreateUnifiedDiff (const std::vector< std::string > &left, const std::vector< std::string > &right, size_t context=2)
 

Enumeration Type Documentation

Enumerator
kMatch 
kAdd 
kRemove 
kReplace 
kMatch 
kAdd 
kRemove 
kReplace 
kMatch 
kAdd 
kRemove 
kReplace 

Definition at line 180 of file gtest-internal.h.

Enumerator
kMatch 
kAdd 
kRemove 
kReplace 
kMatch 
kAdd 
kRemove 
kReplace 
kMatch 
kAdd 
kRemove 
kReplace 

Definition at line 180 of file gtest-internal.h.

Enumerator
kMatch 
kAdd 
kRemove 
kReplace 
kMatch 
kAdd 
kRemove 
kReplace 
kMatch 
kAdd 
kRemove 
kReplace 

Definition at line 180 of file gtest-internal.h.

Function Documentation

std::vector< EditType > testing::internal::edit_distance::CalculateOptimalEdits ( const std::vector< size_t > &  left,
const std::vector< size_t > &  right 
)

Definition at line 1028 of file gtest.cc.

References add, ids_, kAdd, kMatch, kRemove, kReplace, folly::gen::move, replace(), and string.

Referenced by CalculateOptimalEdits(), CreateUnifiedDiff(), testing::internal::ShouldRunTestCase(), and testing::internal::UnitTestRecordPropertyTestHelper::UnitTestRecordProperty().

1029  {
1030  std::vector<std::vector<double> > costs(
1031  left.size() + 1, std::vector<double>(right.size() + 1));
1032  std::vector<std::vector<EditType> > best_move(
1033  left.size() + 1, std::vector<EditType>(right.size() + 1));
1034 
1035  // Populate for empty right.
1036  for (size_t l_i = 0; l_i < costs.size(); ++l_i) {
1037  costs[l_i][0] = static_cast<double>(l_i);
1038  best_move[l_i][0] = kRemove;
1039  }
1040  // Populate for empty left.
1041  for (size_t r_i = 1; r_i < costs[0].size(); ++r_i) {
1042  costs[0][r_i] = static_cast<double>(r_i);
1043  best_move[0][r_i] = kAdd;
1044  }
1045 
1046  for (size_t l_i = 0; l_i < left.size(); ++l_i) {
1047  for (size_t r_i = 0; r_i < right.size(); ++r_i) {
1048  if (left[l_i] == right[r_i]) {
1049  // Found a match. Consume it.
1050  costs[l_i + 1][r_i + 1] = costs[l_i][r_i];
1051  best_move[l_i + 1][r_i + 1] = kMatch;
1052  continue;
1053  }
1054 
1055  const double add = costs[l_i + 1][r_i];
1056  const double remove = costs[l_i][r_i + 1];
1057  const double replace = costs[l_i][r_i];
1058  if (add < remove && add < replace) {
1059  costs[l_i + 1][r_i + 1] = add + 1;
1060  best_move[l_i + 1][r_i + 1] = kAdd;
1061  } else if (remove < add && remove < replace) {
1062  costs[l_i + 1][r_i + 1] = remove + 1;
1063  best_move[l_i + 1][r_i + 1] = kRemove;
1064  } else {
1065  // We make replace a little more expensive than add/remove to lower
1066  // their priority.
1067  costs[l_i + 1][r_i + 1] = replace + 1.00001;
1068  best_move[l_i + 1][r_i + 1] = kReplace;
1069  }
1070  }
1071  }
1072 
1073  // Reconstruct the best path. We do it in reverse order.
1074  std::vector<EditType> best_path;
1075  for (size_t l_i = left.size(), r_i = right.size(); l_i > 0 || r_i > 0;) {
1076  EditType move = best_move[l_i][r_i];
1077  best_path.push_back(move);
1078  l_i -= move != kAdd;
1079  r_i -= move != kRemove;
1080  }
1081  std::reverse(best_path.begin(), best_path.end());
1082  return best_path;
1083 }
auto add
Definition: BaseTest.cpp:70
constexpr detail::Map< Move > move
Definition: Base-inl.h:2567
void BENCHFUN() replace(size_t iters, size_t arg)
std::vector< EditType > testing::internal::edit_distance::CalculateOptimalEdits ( const std::vector< std::string > &  left,
const std::vector< std::string > &  right 
)

Definition at line 1104 of file gtest.cc.

References adds_, CalculateOptimalEdits(), common_, hunk_, hunk_adds_, hunk_removes_, i, left_start_, bm::list, testing::internal::PrintTo(), removes_, and right_start_.

1106  {
1107  std::vector<size_t> left_ids, right_ids;
1108  {
1109  InternalStrings intern_table;
1110  for (size_t i = 0; i < left.size(); ++i) {
1111  left_ids.push_back(intern_table.GetId(left[i]));
1112  }
1113  for (size_t i = 0; i < right.size(); ++i) {
1114  right_ids.push_back(intern_table.GetId(right[i]));
1115  }
1116  }
1117  return CalculateOptimalEdits(left_ids, right_ids);
1118 }
GTEST_API_ std::vector< EditType > CalculateOptimalEdits(const std::vector< size_t > &left, const std::vector< size_t > &right)
Definition: gtest.cc:1028
std::string testing::internal::edit_distance::CreateUnifiedDiff ( const std::vector< std::string > &  left,
const std::vector< std::string > &  right,
size_t  context = 2 
)

Definition at line 1203 of file gtest.cc.

References CalculateOptimalEdits(), folly::test::end(), i, kAdd, kMatch, kRemove, kReplace, folly::gen::lines(), min, start, and string.

Referenced by testing::internal::EqFailure(), and testing::internal::UnitTestRecordPropertyTestHelper::UnitTestRecordProperty().

1205  {
1206  const std::vector<EditType> edits = CalculateOptimalEdits(left, right);
1207 
1208  size_t l_i = 0, r_i = 0, edit_i = 0;
1209  std::stringstream ss;
1210  while (edit_i < edits.size()) {
1211  // Find first edit.
1212  while (edit_i < edits.size() && edits[edit_i] == kMatch) {
1213  ++l_i;
1214  ++r_i;
1215  ++edit_i;
1216  }
1217 
1218  // Find the first line to include in the hunk.
1219  const size_t prefix_context = std::min(l_i, context);
1220  Hunk hunk(l_i - prefix_context + 1, r_i - prefix_context + 1);
1221  for (size_t i = prefix_context; i > 0; --i) {
1222  hunk.PushLine(' ', left[l_i - i].c_str());
1223  }
1224 
1225  // Iterate the edits until we found enough suffix for the hunk or the input
1226  // is over.
1227  size_t n_suffix = 0;
1228  for (; edit_i < edits.size(); ++edit_i) {
1229  if (n_suffix >= context) {
1230  // Continue only if the next hunk is very close.
1231  std::vector<EditType>::const_iterator it = edits.begin() + edit_i;
1232  while (it != edits.end() && *it == kMatch) ++it;
1233  if (it == edits.end() || (it - edits.begin()) - edit_i >= context) {
1234  // There is no next edit or it is too far away.
1235  break;
1236  }
1237  }
1238 
1239  EditType edit = edits[edit_i];
1240  // Reset count when a non match is found.
1241  n_suffix = edit == kMatch ? n_suffix + 1 : 0;
1242 
1243  if (edit == kMatch || edit == kRemove || edit == kReplace) {
1244  hunk.PushLine(edit == kMatch ? ' ' : '-', left[l_i].c_str());
1245  }
1246  if (edit == kAdd || edit == kReplace) {
1247  hunk.PushLine('+', right[r_i].c_str());
1248  }
1249 
1250  // Advance indices, depending on edit type.
1251  l_i += edit != kAdd;
1252  r_i += edit != kRemove;
1253  }
1254 
1255  if (!hunk.has_edits()) {
1256  // We are done. We don't want this hunk.
1257  break;
1258  }
1259 
1260  hunk.PrintTo(&ss);
1261  }
1262  return ss.str();
1263 }
GTEST_API_ std::vector< EditType > CalculateOptimalEdits(const std::vector< size_t > &left, const std::vector< size_t > &right)
Definition: gtest.cc:1028
context
Definition: CMakeCache.txt:563
LogLevel min
Definition: LogLevel.cpp:30