@@ -676,13 +676,14 @@ Future<RangeResult> ConflictingKeysImpl::getRange(ReadYourWritesTransaction* ryw
676676 if (ryw->getTransactionState ()->conflictingKeys ) {
677677 auto krMapPtr = ryw->getTransactionState ()->conflictingKeys .get ();
678678 auto beginIter = krMapPtr->rangeContaining (kr.begin );
679- if (beginIter->begin () != kr.begin )
680- ++beginIter;
681679 auto endIter = krMapPtr->rangeContaining (kr.end );
680+
681+ if (!kr.contains (beginIter->begin ()) && beginIter != endIter)
682+ ++beginIter;
682683 for (auto it = beginIter; it != endIter; ++it) {
683684 result.push_back_deep (result.arena (), KeyValueRef (it->begin (), it->value ()));
684685 }
685- if (endIter->begin () != kr. end )
686+ if (kr. contains ( endIter->begin ()) )
686687 result.push_back_deep (result.arena (), KeyValueRef (endIter->begin (), endIter->value ()));
687688 }
688689 return result;
@@ -2817,3 +2818,85 @@ Future<Optional<std::string>> TenantMapRangeImpl::commit(ReadYourWritesTransacti
28172818
28182819 return tag (waitForAll (tenantManagementFutures), Optional<std::string>());
28192820}
2821+
2822+ ACTOR Future<Void> validateSpecialSubrangeRead (ReadYourWritesTransaction* ryw,
2823+ KeySelector begin,
2824+ KeySelector end,
2825+ GetRangeLimits limits,
2826+ Reverse reverse,
2827+ RangeResult result) {
2828+ if (!result.size ()) {
2829+ RangeResult testResult = wait (ryw->getRange (begin, end, limits, Snapshot::True, reverse));
2830+ ASSERT (testResult == result);
2831+ return Void ();
2832+ }
2833+
2834+ if (reverse) {
2835+ ASSERT (std::is_sorted (result.begin (), result.end (), KeyValueRef::OrderByKeyBack{}));
2836+ } else {
2837+ ASSERT (std::is_sorted (result.begin (), result.end (), KeyValueRef::OrderByKey{}));
2838+ }
2839+
2840+ // Generate a keyrange where we can determine the expected result based solely on the previous readrange, and whose
2841+ // boundaries may or may not be keys in result.
2842+ std::vector<Key> candidateKeys;
2843+ if (reverse) {
2844+ for (int i = result.size () - 1 ; i >= 0 ; --i) {
2845+ candidateKeys.emplace_back (result[i].key );
2846+ if (i - 1 >= 0 ) {
2847+ candidateKeys.emplace_back (keyBetween (KeyRangeRef (result[i].key , result[i - 1 ].key )));
2848+ }
2849+ }
2850+ } else {
2851+ for (int i = 0 ; i < result.size (); ++i) {
2852+ candidateKeys.emplace_back (result[i].key );
2853+ if (i + 1 < result.size ()) {
2854+ candidateKeys.emplace_back (keyBetween (KeyRangeRef (result[i].key , result[i + 1 ].key )));
2855+ }
2856+ }
2857+ }
2858+ std::sort (candidateKeys.begin (), candidateKeys.end ());
2859+ int originalSize = candidateKeys.size ();
2860+ // Add more candidate keys so that we might read a range between two adjacent result keys.
2861+ for (int i = 0 ; i < originalSize - 1 ; ++i) {
2862+ candidateKeys.emplace_back (keyBetween (KeyRangeRef (candidateKeys[i], candidateKeys[i + 1 ])));
2863+ }
2864+ std::vector<Key> keys;
2865+ keys = { deterministicRandom ()->randomChoice (candidateKeys), deterministicRandom ()->randomChoice (candidateKeys) };
2866+ std::sort (keys.begin (), keys.end ());
2867+ state KeySelector testBegin = firstGreaterOrEqual (keys[0 ]);
2868+ state KeySelector testEnd = firstGreaterOrEqual (keys[1 ]);
2869+
2870+ // Generate expected result. Linear time is ok here since we're in simulation, and there's a benefit to keeping this
2871+ // simple (as we're using it as an test oracle)
2872+ state RangeResult expectedResult;
2873+ // The reverse parameter should be the same as for the original read, so if
2874+ // reverse is true then the results are _already_ in reverse order.
2875+ for (const auto & kr : result) {
2876+ if (kr.key >= keys[0 ] && kr.key < keys[1 ]) {
2877+ expectedResult.push_back (expectedResult.arena (), kr);
2878+ }
2879+ }
2880+
2881+ // Test
2882+ RangeResult testResult = wait (ryw->getRange (testBegin, testEnd, limits, Snapshot::True, reverse));
2883+ if (testResult != expectedResult) {
2884+ fmt::print (" Reverse: {}\n " , reverse);
2885+ fmt::print (" Original range: [{}, {})\n " , begin.toString (), end.toString ());
2886+ fmt::print (" Original result:\n " );
2887+ for (const auto & kr : result) {
2888+ fmt::print (" {} -> {}\n " , kr.key .printable (), kr.value .printable ());
2889+ }
2890+ fmt::print (" Test range: [{}, {})\n " , testBegin.getKey ().printable (), testEnd.getKey ().printable ());
2891+ fmt::print (" Expected:\n " );
2892+ for (const auto & kr : expectedResult) {
2893+ fmt::print (" {} -> {}\n " , kr.key .printable (), kr.value .printable ());
2894+ }
2895+ fmt::print (" Got:\n " );
2896+ for (const auto & kr : testResult) {
2897+ fmt::print (" {} -> {}\n " , kr.key .printable (), kr.value .printable ());
2898+ }
2899+ ASSERT (testResult == expectedResult);
2900+ }
2901+ return Void ();
2902+ }
0 commit comments