TEST_F(DisplayItemPropertyTreeBuilderTest, TransformDisplayItemCreatesTransformNode) { // 2D transform display items should create a transform node as well, // unless the transform is a 2D translation only. AffineTransform rotation; rotation.rotate(45); processDummyDisplayItem(); auto transformClient = processBeginTransform(rotation); processDummyDisplayItem(); processEndTransform(transformClient); processDummyDisplayItem(); finishPropertyTrees(); // There should be two transform nodes. ASSERT_EQ(2u, transformTree().nodeCount()); EXPECT_TRUE(transformTree().nodeAt(0).isRoot()); EXPECT_EQ(0u, transformTree().nodeAt(1).parentNodeIndex); EXPECT_TRANSFORMS_ALMOST_EQ(TransformationMatrix(rotation), transformTree().nodeAt(1).matrix); // There should be three range records, the middle one affected by the // rotation. EXPECT_THAT(rangeRecordsAsStdVector(), ElementsAre( AllOf(hasRange(0, 1), hasTransformNode(0)), AllOf(hasRange(2, 3), hasTransformNode(1)), AllOf(hasRange(4, 5), hasTransformNode(0)))); }
TEST_F(DisplayItemPropertyTreeBuilderTest, Only2DTranslation) { FloatSize offset(200.5, -100); TransformationMatrix translation; translation.translate(offset.width(), offset.height()); // There's a translation here, but we should not make a node for it. processDummyDisplayItem(); auto transformClient = processBeginTransform3D(translation); processDummyDisplayItem(); processEndTransform3D(transformClient); processDummyDisplayItem(); finishPropertyTrees(); // There should only be a root transform node. ASSERT_EQ(1u, transformTree().nodeCount()); EXPECT_TRUE(transformTree().nodeAt(0).isRoot()); // There should be three ranges, even though there's only one node. // The middle one requires an offset. EXPECT_THAT(rangeRecordsAsStdVector(), ElementsAre( AllOf(hasRange(0, 1), hasTransformNode(0)), AllOf(hasRange(2, 3), hasTransformNode(0)), AllOf(hasRange(4, 5), hasTransformNode(0)))); }
TEST_F(DisplayItemPropertyTreeBuilderTest, SkipUnnecessaryRangeRecords) { TransformationMatrix rotation; rotation.rotate(1 /* degrees */); // The only drawing is in the second transform. auto transform1 = processBeginTransform3D(rotation); auto transform2 = processBeginTransform3D(rotation); processDummyDisplayItem(); auto transform3 = processBeginTransform3D(rotation); processEndTransform3D(transform3); processDummyDisplayItem(); processEndTransform3D(transform2); processEndTransform3D(transform1); finishPropertyTrees(); // There should be only two ranges. // They must both belong to the same grandchild of the root node. ASSERT_EQ(2u, rangeRecords().size()); size_t transformNodeIndex = rangeRecords()[0].transformNodeIndex; EXPECT_EQ(2u, nodeDepth(transformTree(), transformTree().nodeAt(transformNodeIndex))); EXPECT_THAT(rangeRecordsAsStdVector(), ElementsAre( AllOf(hasRange(2, 3), hasTransformNode(transformNodeIndex)), AllOf(hasRange(5, 6), hasTransformNode(transformNodeIndex)))); }
TEST_F(DisplayItemPropertyTreeBuilderTest, ZTranslation) { TransformationMatrix zTranslation; zTranslation.translate3d(0, 0, 1); // Z translation: we expect another node. processDummyDisplayItem(); auto transformClient = processBeginTransform3D(zTranslation); processDummyDisplayItem(); processEndTransform3D(transformClient); processDummyDisplayItem(); finishPropertyTrees(); // There should be two nodes here. ASSERT_EQ(2u, transformTree().nodeCount()); EXPECT_TRUE(transformTree().nodeAt(0).isRoot()); EXPECT_EQ(0u, transformTree().nodeAt(1).parentNodeIndex); // There should be three range records. // The middle of these should be transformed, and the others should be // attached to the root node. EXPECT_THAT(rangeRecordsAsStdVector(), ElementsAre( AllOf(hasRange(0, 1), hasTransformNode(0)), AllOf(hasRange(2, 3), hasTransformNode(1)), AllOf(hasRange(4, 5), hasTransformNode(0)))); }
TEST_F(DisplayItemPropertyTreeBuilderTest, Nested2DTranslation) { FloatSize offset1(10, -40); TransformationMatrix translation1; translation1.translate(offset1.width(), offset1.height()); FloatSize offset2(80, 80); TransformationMatrix translation2; translation2.translate(offset2.width(), offset2.height()); // These drawings should share a transform node but have different range // record offsets. processDummyDisplayItem(); auto transform1 = processBeginTransform3D(translation1); processDummyDisplayItem(); auto transform2 = processBeginTransform3D(translation2); processDummyDisplayItem(); processEndTransform3D(transform2); processEndTransform3D(transform1); finishPropertyTrees(); // There should only be a root transform node. ASSERT_EQ(1u, transformTree().nodeCount()); EXPECT_TRUE(transformTree().nodeAt(0).isRoot()); // Check that the range records have the right offsets. EXPECT_THAT(rangeRecordsAsStdVector(), ElementsAre( AllOf(hasRange(0, 1), hasTransformNode(0), hasOffset(FloatSize())), AllOf(hasRange(2, 3), hasTransformNode(0), hasOffset(offset1)), AllOf(hasRange(4, 5), hasTransformNode(0), hasOffset(offset1 + offset2)))); }
TEST_F(BaseTestSpecTests, TestSuite_WithGroups) { RawTestSuite rawTestSuite = specWithTestGroups.buildRawTestSuite(); EXPECT_THAT(rawTestSuite.sampleTests(), SizeIs(2)); EXPECT_THAT(rawTestSuite.officialTests(), ElementsAre( AllOf(Property(&OfficialTestGroup::id, 1), Property(&OfficialTestGroup::officialTestCases, SizeIs(3))), AllOf(Property(&OfficialTestGroup::id, 2), Property(&OfficialTestGroup::officialTestCases, SizeIs(2))))); }
TEST_F(ClangQueryGatherer, FilterDuplicates) { manyGatherer.setProcessingSlotCount(3); manyGatherer.startCreateNextSourceRangesMessages(); manyGatherer.waitForFinished(); auto messages = manyGatherer.finishedMessages(); ASSERT_THAT(messages, AllOf(SizeIs(3), UnorderedElementsAre( Field(&SourceRangesForQueryMessage::sourceRanges, Field(&SourceRangesContainer::sourceRangeWithTextContainers, UnorderedElementsAre( IsSourceRangeWithText(1, 1, 1, 9, "void f();"), IsSourceRangeWithText(2, 1, 2, 12, "void f() {}")))), Field(&SourceRangesForQueryMessage::sourceRanges, Field(&SourceRangesContainer::sourceRangeWithTextContainers, UnorderedElementsAre( IsSourceRangeWithText(1, 1, 1, 13, "int header();"), IsSourceRangeWithText(3, 1, 3, 15, "int function();")))), Field(&SourceRangesForQueryMessage::sourceRanges, Field(&SourceRangesContainer::sourceRangeWithTextContainers, UnorderedElementsAre( IsSourceRangeWithText(3, 1, 3, 15, "int function();"))))))); }
TEST(DiagnosticsTest, FlagsMatter) { Annotations Test("[[void]] main() {}"); EXPECT_THAT(buildDiags(Test.code()), ElementsAre(DiagWithEqualFix(Test.range(), "int", "'main' must return 'int'"))); // Same code built as C gets different diagnostics. EXPECT_THAT( buildDiags(Test.code(), {"-x", "c"}), ElementsAre(AllOf( Diag(Test.range(), "return type of 'main' is not 'int'"), WithFix(Fix(Test.range(), "int", "change return type to 'int'"))))); }
TEST_F(DisplayItemPropertyTreeBuilderTest, ScrollDisplayItemIs2DTranslation) { processDummyDisplayItem(); auto scrollClient = processBeginScroll(-90, 400); processDummyDisplayItem(); processEndScroll(scrollClient); processDummyDisplayItem(); finishPropertyTrees(); // There should be only one transform node. ASSERT_EQ(1u, transformTree().nodeCount()); EXPECT_TRUE(transformTree().nodeAt(0).isRoot()); // There should be three range records, the middle one affected by the // scroll. Note that the translation due to scroll is the negative of the // scroll offset. EXPECT_THAT(rangeRecordsAsStdVector(), ElementsAre( AllOf(hasRange(0, 1), hasTransformNode(0), hasOffset(FloatSize(0, 0))), AllOf(hasRange(2, 3), hasTransformNode(0), hasOffset(FloatSize(90, -400))), AllOf(hasRange(4, 5), hasTransformNode(0), hasOffset(FloatSize(0, 0))))); }
TEST_F(DisplayItemPropertyTreeBuilderTest, TransformDisplayItemOnly2DTranslation) { // In this case no transform node should be created for the 2D translation. AffineTransform translation = AffineTransform::translation(10, -40); processDummyDisplayItem(); auto transformClient = processBeginTransform(translation); processDummyDisplayItem(); processEndTransform(transformClient); processDummyDisplayItem(); finishPropertyTrees(); // There should be only one transform node. ASSERT_EQ(1u, transformTree().nodeCount()); EXPECT_TRUE(transformTree().nodeAt(0).isRoot()); // There should be three range records, the middle one affected by the // translation. EXPECT_THAT(rangeRecordsAsStdVector(), ElementsAre( AllOf(hasRange(0, 1), hasTransformNode(0), hasOffset(FloatSize(0, 0))), AllOf(hasRange(2, 3), hasTransformNode(0), hasOffset(FloatSize(10, -40))), AllOf(hasRange(4, 5), hasTransformNode(0), hasOffset(FloatSize(0, 0))))); }
TEST_F(DisplayItemPropertyTreeBuilderTest, IdentityTransform) { TransformationMatrix identity; // There's an identity transform here, but we should not make a node for it. processDummyDisplayItem(); auto transformClient = processBeginTransform3D(identity); processDummyDisplayItem(); processEndTransform3D(transformClient); processDummyDisplayItem(); finishPropertyTrees(); // There should only be a root transform node. ASSERT_EQ(1u, transformTree().nodeCount()); EXPECT_TRUE(transformTree().nodeAt(0).isRoot()); // There should be three range records. // Since the transform is the identity, these could be combined, but there // is not currently a special path for this case. EXPECT_THAT(rangeRecordsAsStdVector(), ElementsAre( AllOf(hasRange(0, 1), hasTransformNode(0)), AllOf(hasRange(2, 3), hasTransformNode(0)), AllOf(hasRange(4, 5), hasTransformNode(0)))); }
void TestTermination( Integrator const& integrator) { Length const q_initial = 1 * Metre; Speed const v_initial = 0 * Metre / Second; Instant const t_initial; Instant const t_final = t_initial + 163 * Second; Time const step = 42 * Second; int const steps = static_cast<int>(std::floor((t_final - t_initial) / step)); int evaluations = 0; std::vector<ODE::SystemState> solution; ODE harmonic_oscillator; harmonic_oscillator.compute_acceleration = std::bind(ComputeHarmonicOscillatorAcceleration, _1, _2, _3, &evaluations); IntegrationProblem<ODE> problem; problem.equation = harmonic_oscillator; ODE::SystemState const initial_state = {{q_initial}, {v_initial}, t_initial}; problem.initial_state = &initial_state; problem.t_final = t_final; problem.append_state = [&solution](ODE::SystemState const& state) { solution.push_back(state); }; integrator.Solve(problem, step); EXPECT_EQ(steps, solution.size()); EXPECT_THAT(solution.back().time.value, AllOf(Gt(t_final - step), Le(t_final))); switch (integrator.composition) { case BA: case ABA: EXPECT_EQ(steps * integrator.evaluations, evaluations); break; case BAB: EXPECT_EQ(steps * integrator.evaluations + 1, evaluations); break; default: LOG(FATAL) << "Invalid composition"; } Length q_error; Speed v_error; for (int i = 0; i < steps; ++i) { Time const t = solution[i].time.value - t_initial; EXPECT_THAT(t, AlmostEquals((i + 1) * step, 0)); } }
TEST_F(ClangQueryGatherer, GetFinishedMessagesAfterSecondPass) { manyGatherer.startCreateNextSourceRangesMessages(); manyGatherer.waitForFinished(); manyGatherer.finishedMessages(); manyGatherer.startCreateNextSourceRangesMessages(); manyGatherer.waitForFinished(); auto messages = manyGatherer.finishedMessages(); ASSERT_THAT(messages, AllOf(SizeIs(1), ElementsAre( Field(&SourceRangesForQueryMessage::sourceRanges, Field(&SourceRangesContainer::sourceRangeWithTextContainers, UnorderedElementsAre( IsSourceRangeWithText(3, 1, 3, 15, "int function();"))))))); }
// Solving Δt * Δt == n. TEST_F(RootFindersTest, SquareRoots) { Instant const t_0; Instant const t_max = t_0 + 10 * Second; Length const n_max = Pow<2>(t_max - t_0) * SIUnit<Acceleration>(); for (Length n = 1 * Metre; n < n_max; n += 1 * Metre) { int evaluations = 0; auto const equation = [t_0, n, &evaluations](Instant const& t) { ++evaluations; return Pow<2>(t - t_0) * SIUnit<Acceleration>() - n; }; EXPECT_THAT(Bisect(equation, t_0, t_max) - t_0, AlmostEquals(Sqrt(n / SIUnit<Acceleration>()), 0, 1)); if (n == 25 * Metre) { EXPECT_EQ(3, evaluations); } else { EXPECT_THAT(evaluations, AllOf(Ge(49), Le(58))); } } }
void TestTermination(Integrator const& integrator) { Length const q_initial = 1 * Metre; Speed const v_initial = 0 * Metre / Second; Instant const t_initial; Instant const t_final = t_initial + 1630 * Second; Time const step = 42 * Second; int const steps = static_cast<int>(std::floor((t_final - t_initial) / step)); int evaluations = 0; std::vector<ODE::SystemState> solution; ODE harmonic_oscillator; harmonic_oscillator.compute_acceleration = std::bind(ComputeHarmonicOscillatorAcceleration, _1, _2, _3, &evaluations); IntegrationProblem<ODE> problem; problem.equation = harmonic_oscillator; ODE::SystemState const initial_state = {{q_initial}, {v_initial}, t_initial}; problem.initial_state = &initial_state; auto append_state = [&solution](ODE::SystemState const& state) { solution.push_back(state); }; auto const instance = integrator.NewInstance(problem, std::move(append_state), step); integrator.Solve(t_final, *instance); EXPECT_EQ(steps, solution.size()); EXPECT_THAT(solution.back().time.value, AllOf(Gt(t_final - step), Le(t_final))); Length q_error; Speed v_error; for (int i = 0; i < steps; ++i) { Time const t = solution[i].time.value - t_initial; EXPECT_THAT(t, AlmostEquals((i + 1) * step, 0)); } }
void TestConvergence(Integrator const& integrator, Time const& beginning_of_convergence) { Length const q_initial = 1 * Metre; Speed const v_initial = 0 * Metre / Second; Speed const v_amplitude = 1 * Metre / Second; AngularFrequency const ω = 1 * Radian / Second; Instant const t_initial; Instant const t_final = t_initial + 100 * Second; Time step = beginning_of_convergence; int const step_sizes = 50; double const step_reduction = 1.1; std::vector<double> log_step_sizes; log_step_sizes.reserve(step_sizes); std::vector<double> log_q_errors; log_step_sizes.reserve(step_sizes); std::vector<double> log_p_errors; log_step_sizes.reserve(step_sizes); std::vector<ODE::SystemState> solution; ODE harmonic_oscillator; harmonic_oscillator.compute_acceleration = std::bind(ComputeHarmonicOscillatorAcceleration, _1, _2, _3, /*evaluations=*/nullptr); IntegrationProblem<ODE> problem; problem.equation = harmonic_oscillator; ODE::SystemState const initial_state = {{q_initial}, {v_initial}, t_initial}; problem.initial_state = &initial_state; ODE::SystemState final_state; auto const append_state = [&final_state](ODE::SystemState const& state) { final_state = state; }; for (int i = 0; i < step_sizes; ++i, step /= step_reduction) { auto const instance = integrator.NewInstance(problem, append_state, step); integrator.Solve(t_final, *instance); Time const t = final_state.time.value - t_initial; Length const& q = final_state.positions[0].value; Speed const& v = final_state.velocities[0].value; double const log_q_error = std::log10( AbsoluteError(q / q_initial, Cos(ω * t))); double const log_p_error = std::log10( AbsoluteError(v / v_amplitude, -Sin(ω * t))); if (log_q_error <= -13 || log_p_error <= -13) { // If we keep going the effects of finite precision will drown out // convergence. break; } log_step_sizes.push_back(std::log10(step / Second)); log_q_errors.push_back(log_q_error); log_p_errors.push_back(log_p_error); } double const q_convergence_order = Slope(log_step_sizes, log_q_errors); double const q_correlation = PearsonProductMomentCorrelationCoefficient(log_step_sizes, log_q_errors); LOG(INFO) << "Convergence order in q : " << q_convergence_order; LOG(INFO) << "Correlation : " << q_correlation; #if !defined(_DEBUG) EXPECT_THAT(RelativeError(integrator.order, q_convergence_order), Lt(0.05)); EXPECT_THAT(q_correlation, AllOf(Gt(0.99), Lt(1.01))); #endif double const v_convergence_order = Slope(log_step_sizes, log_p_errors); double const v_correlation = PearsonProductMomentCorrelationCoefficient(log_step_sizes, log_p_errors); LOG(INFO) << "Convergence order in p : " << v_convergence_order; LOG(INFO) << "Correlation : " << v_correlation; #if !defined(_DEBUG) // SPRKs with odd convergence order have a higher convergence order in p. EXPECT_THAT( RelativeError(integrator.order + (integrator.order % 2), v_convergence_order), Lt(0.03)); EXPECT_THAT(v_correlation, AllOf(Gt(0.99), Lt(1.01))); #endif }
TEST(URITest, Parse) { EXPECT_THAT(parseOrDie("file://auth/x/y/z"), AllOf(Scheme("file"), Authority("auth"), Body("/x/y/z"))); EXPECT_THAT(parseOrDie("file://au%3dth/%28x%29/y/%5c%20z"), AllOf(Scheme("file"), Authority("au=th"), Body("/(x)/y/\\ z"))); EXPECT_THAT(parseOrDie("file:///%28x%29/y/%5c%20z"), AllOf(Scheme("file"), Authority(""), Body("/(x)/y/\\ z"))); EXPECT_THAT(parseOrDie("file:///x/y/z"), AllOf(Scheme("file"), Authority(""), Body("/x/y/z"))); EXPECT_THAT(parseOrDie("file:"), AllOf(Scheme("file"), Authority(""), Body(""))); EXPECT_THAT(parseOrDie("file:///x/y/z%2"), AllOf(Scheme("file"), Authority(""), Body("/x/y/z%2"))); EXPECT_THAT(parseOrDie("http://llvm.org"), AllOf(Scheme("http"), Authority("llvm.org"), Body(""))); EXPECT_THAT(parseOrDie("http://llvm.org/"), AllOf(Scheme("http"), Authority("llvm.org"), Body("/"))); EXPECT_THAT(parseOrDie("http://llvm.org/D"), AllOf(Scheme("http"), Authority("llvm.org"), Body("/D"))); EXPECT_THAT(parseOrDie("http:/"), AllOf(Scheme("http"), Authority(""), Body("/"))); EXPECT_THAT(parseOrDie("urn:isbn:0451450523"), AllOf(Scheme("urn"), Authority(""), Body("isbn:0451450523"))); EXPECT_THAT( parseOrDie("file:///c:/windows/system32/"), AllOf(Scheme("file"), Authority(""), Body("/c:/windows/system32/"))); }
TEST_P(SimpleHarmonicMotionTest, Convergence) { parameters_.initial.positions.emplace_back(SIUnit<Length>()); parameters_.initial.momenta.emplace_back(Speed()); parameters_.initial.time = Time(); #if defined(_DEBUG) parameters_.tmax = 1 * SIUnit<Time>(); #else parameters_.tmax = 100 * SIUnit<Time>(); #endif parameters_.sampling_period = 0; parameters_.Δt = GetParam().beginning_of_convergence; int const step_sizes = 50; double const step_reduction = 1.1; std::vector<double> log_step_sizes; log_step_sizes.reserve(step_sizes); std::vector<double> log_q_errors; log_step_sizes.reserve(step_sizes); std::vector<double> log_p_errors; log_step_sizes.reserve(step_sizes); for (int i = 0; i < step_sizes; ++i, parameters_.Δt /= step_reduction) { integrator_->SolveTrivialKineticEnergyIncrement<Length>( &ComputeHarmonicOscillatorAcceleration, parameters_, &solution_); double const log_q_error = std::log10( std::abs(solution_[0].positions[0].value / SIUnit<Length>() - Cos(solution_[0].time.value * SIUnit<AngularFrequency>()))); double const log_p_error = std::log10( std::abs(solution_[0].momenta[0].value / SIUnit<Speed>() + Sin(solution_[0].time.value * SIUnit<AngularFrequency>()))); if (log_q_error <= -13 || log_p_error <= -13) { // If we keep going the effects of finite precision will drown out // convergence. break; } log_step_sizes.push_back(std::log10(parameters_.Δt / SIUnit<Time>())); log_q_errors.push_back(log_q_error); log_p_errors.push_back(log_p_error); } double const q_convergence_order = Slope(log_step_sizes, log_q_errors); double const q_correlation = PearsonProductMomentCorrelationCoefficient(log_step_sizes, log_q_errors); LOG(INFO) << GetParam(); LOG(INFO) << "Convergence order in q : " << q_convergence_order; LOG(INFO) << "Correlation : " << q_correlation; #if 0 LOG(INFO) << "Convergence data for q :\n" << BidimensionalDatasetMathematicaInput(log_step_sizes, log_q_errors); #endif #if !defined(_DEBUG) EXPECT_THAT(RelativeError(GetParam().convergence_order, q_convergence_order), Lt(0.02)); EXPECT_THAT(q_correlation, AllOf(Gt(0.99), Lt(1.01))); #endif double const v_convergence_order = Slope(log_step_sizes, log_p_errors); double const v_correlation = PearsonProductMomentCorrelationCoefficient(log_step_sizes, log_p_errors); LOG(INFO) << "Convergence order in p : " << v_convergence_order; LOG(INFO) << "Correlation : " << v_correlation; #if 0 LOG(INFO) << "Convergence data for p :\n" << BidimensionalDatasetMathematicaInput(log_step_sizes, log_q_errors); #endif #if !defined(_DEBUG) // SPRKs with odd convergence order have a higher convergence order in p. EXPECT_THAT( RelativeError(((GetParam().convergence_order + 1) / 2) * 2, v_convergence_order), Lt(0.02)); EXPECT_THAT(v_correlation, AllOf(Gt(0.99), Lt(1.01))); #endif }
TEST_F(ManœuvreTest, Apollo8SIVB) { // Data from NASA's Saturn V Launch Vehicle, Flight Evaluation Report AS-503, // Apollo 8 Mission (1969), // http://ntrs.nasa.gov/archive/nasa/casi.ntrs.nasa.gov/19690015314.pdf. // We use the reconstructed or actual values. // Table 2-2. Significant Event Times Summary. Instant const range_zero; Instant const s_ivb_1st_90_percent_thrust = range_zero + 530.53 * Second; Instant const s_ivb_1st_eco = range_zero + 684.98 * Second; // Initiate S-IVB Restart Sequence and Start of Time Base 6 (T6). Instant const t6 = range_zero + 9659.54 * Second; Instant const s_ivb_2nd_90_percent_thrust = range_zero + 10'240.02 * Second; Instant const s_ivb_2nd_eco = range_zero + 10'555.51 * Second; // From Table 7-2. S-IVB Steady State Performance - First Burn. Force thrust_1st = 901'557 * Newton; Speed specific_impulse_1st = 4'204.1 * Newton * Second / Kilogram; Variation<Mass> lox_flowrate_1st = 178.16 * Kilogram / Second; Variation<Mass> fuel_flowrate_1st = 36.30 * Kilogram / Second; // From Table 7-7. S-IVB Steady State Performance - Second Burn. Force thrust_2nd = 897'548 * Newton; Speed specific_impulse_2nd = 4199.2 * Newton * Second / Kilogram; Variation<Mass> lox_flowrate_2nd = 177.70 * Kilogram / Second; Variation<Mass> fuel_flowrate_2nd = 36.01 * Kilogram / Second; // Table 21-5. Total Vehicle Mass, S-IVB First Burn Phase, Kilograms. Mass total_vehicle_at_s_ivb_1st_90_percent_thrust = 161143 * Kilogram; Mass total_vehicle_at_s_ivb_1st_eco = 128095 * Kilogram; // Table 21-7. Total Vehicle Mass, S-IVB Second Burn Phase, Kilograms. Mass total_vehicle_at_s_ivb_2nd_90_percent_thrust = 126780 * Kilogram; Mass total_vehicle_at_s_ivb_2nd_eco = 59285 * Kilogram; // An arbitrary direction, we're not testing this. Vector<double, World> e_y({0, 1, 0}); Manœuvre<World> first_burn(thrust_1st, total_vehicle_at_s_ivb_1st_90_percent_thrust, specific_impulse_1st, e_y); EXPECT_THAT(RelativeError(lox_flowrate_1st + fuel_flowrate_1st, first_burn.mass_flow()), Lt(1E-4)); first_burn.set_duration(s_ivb_1st_eco - s_ivb_1st_90_percent_thrust); EXPECT_THAT( RelativeError(total_vehicle_at_s_ivb_1st_eco, first_burn.final_mass()), Lt(1E-3)); first_burn.set_initial_time(s_ivb_1st_90_percent_thrust); EXPECT_EQ(s_ivb_1st_eco, first_burn.final_time()); // Accelerations from Figure 4-4. Ascent Trajectory Acceleration Comparison. // Final acceleration from Table 4-2. Comparison of Significant Trajectory // Events. EXPECT_THAT( first_burn.acceleration()(first_burn.initial_time()).Norm(), AllOf(Gt(5 * Metre / Pow<2>(Second)), Lt(6.25 * Metre / Pow<2>(Second)))); EXPECT_THAT(first_burn.acceleration()(range_zero + 600 * Second).Norm(), AllOf(Gt(6.15 * Metre / Pow<2>(Second)), Lt(6.35 * Metre / Pow<2>(Second)))); EXPECT_THAT(first_burn.acceleration()(first_burn.final_time()).Norm(), AllOf(Gt(7.03 * Metre / Pow<2>(Second)), Lt(7.05 * Metre / Pow<2>(Second)))); Manœuvre<World> second_burn(thrust_2nd, total_vehicle_at_s_ivb_2nd_90_percent_thrust, specific_impulse_2nd, e_y); EXPECT_THAT(RelativeError(lox_flowrate_2nd + fuel_flowrate_2nd, second_burn.mass_flow()), Lt(2E-4)); second_burn.set_duration(s_ivb_2nd_eco - s_ivb_2nd_90_percent_thrust); EXPECT_THAT( RelativeError(total_vehicle_at_s_ivb_2nd_eco, second_burn.final_mass()), Lt(2E-3)); second_burn.set_initial_time(s_ivb_2nd_90_percent_thrust); EXPECT_EQ(s_ivb_2nd_eco, second_burn.final_time()); // Accelerations from Figure 4-9. Injection Phase Acceleration Comparison. // Final acceleration from Table 4-2. Comparison of Significant Trajectory // Events. EXPECT_THAT(second_burn.acceleration()(second_burn.initial_time()).Norm(), AllOf(Gt(7 * Metre / Pow<2>(Second)), Lt(7.5 * Metre / Pow<2>(Second)))); EXPECT_THAT(second_burn.acceleration()(t6 + 650 * Second).Norm(), AllOf(Gt(8 * Metre / Pow<2>(Second)), Lt(8.02 * Metre / Pow<2>(Second)))); EXPECT_THAT(second_burn.acceleration()(t6 + 700 * Second).Norm(), AllOf(Gt(8.8 * Metre / Pow<2>(Second)), Lt(9 * Metre / Pow<2>(Second)))); EXPECT_THAT(second_burn.acceleration()(t6 + 750 * Second).Norm(), AllOf(Gt(9.9 * Metre / Pow<2>(Second)), Lt(10 * Metre / Pow<2>(Second)))); EXPECT_THAT(second_burn.acceleration()(t6 + 850 * Second).Norm(), AllOf(Gt(12.97 * Metre / Pow<2>(Second)), Lt(13 * Metre / Pow<2>(Second)))); EXPECT_THAT(second_burn.acceleration()(second_burn.final_time()).Norm(), AllOf(Gt(15.12 * Metre / Pow<2>(Second)), Lt(15.17 * Metre / Pow<2>(Second)))); EXPECT_THAT(second_burn.Δv(), AllOf(Gt(3 * Kilo(Metre) / Second), Lt(3.25 * Kilo(Metre) / Second))); // From the Apollo 8 flight journal. EXPECT_THAT(AbsoluteError(10'519.6 * Foot / Second, second_burn.Δv()), Lt(20 * Metre / Second)); }
TEST_F(EmbeddedExplicitRungeKuttaNyströmIntegratorTest, MaxSteps) { AdaptiveStepSizeIntegrator<ODE> const& integrator = DormandElMikkawyPrince1986RKN434FM<Length>(); Length const x_initial = 1 * Metre; Speed const v_initial = 0 * Metre / Second; Speed const v_amplitude = 1 * Metre / Second; Time const period = 2 * π * Second; AngularFrequency const ω = 1 * Radian / Second; Instant const t_initial; Instant const t_final = t_initial + 10 * period; Length const length_tolerance = 1 * Milli(Metre); Speed const speed_tolerance = 1 * Milli(Metre) / Second; // The number of steps if no step limit is set. std::int64_t const steps_forward = 132; int evaluations = 0; auto const step_size_callback = [](bool tolerable) {}; std::vector<ODE::SystemState> solution; ODE harmonic_oscillator; harmonic_oscillator.compute_acceleration = std::bind(ComputeHarmonicOscillatorAcceleration, _1, _2, _3, &evaluations); IntegrationProblem<ODE> problem; problem.equation = harmonic_oscillator; ODE::SystemState const initial_state = {{x_initial}, {v_initial}, t_initial}; problem.initial_state = &initial_state; problem.t_final = t_final; problem.append_state = [&solution](ODE::SystemState const& state) { solution.push_back(state); }; AdaptiveStepSize<ODE> adaptive_step_size; adaptive_step_size.first_time_step = t_final - t_initial; adaptive_step_size.safety_factor = 0.9; adaptive_step_size.tolerance_to_error_ratio = std::bind(HarmonicOscillatorToleranceRatio, _1, _2, length_tolerance, speed_tolerance, step_size_callback); adaptive_step_size.max_steps = 100; auto const outcome = integrator.Solve(problem, adaptive_step_size); EXPECT_EQ(termination_condition::ReachedMaximalStepCount, outcome.error()); EXPECT_THAT(AbsoluteError( x_initial * Cos(ω * (solution.back().time.value - t_initial)), solution.back().positions[0].value), AllOf(Ge(8e-4 * Metre), Le(9e-4 * Metre))); EXPECT_THAT(AbsoluteError( -v_amplitude * Sin(ω * (solution.back().time.value - t_initial)), solution.back().velocities[0].value), AllOf(Ge(1e-3 * Metre / Second), Le(2e-3 * Metre / Second))); EXPECT_THAT(solution.back().time.value, Lt(t_final)); EXPECT_EQ(100, solution.size()); // Check that a |max_steps| greater than or equal to the unconstrained number // of steps has no effect. for (std::int64_t const max_steps : {steps_forward, steps_forward + 1234}) { solution.clear(); adaptive_step_size.max_steps = steps_forward; auto const outcome = integrator.Solve(problem, adaptive_step_size); EXPECT_EQ(termination_condition::Done, outcome.error()); EXPECT_THAT(AbsoluteError(x_initial, solution.back().positions[0].value), AllOf(Ge(3e-4 * Metre), Le(4e-4 * Metre))); EXPECT_THAT(AbsoluteError(v_initial, solution.back().velocities[0].value), AllOf(Ge(2e-3 * Metre / Second), Le(3e-3 * Metre / Second))); EXPECT_EQ(t_final, solution.back().time.value); EXPECT_EQ(steps_forward, solution.size()); } }
Server.addDocument(Path, Contents); } }; } // namespace TEST_F(WorkspaceSymbolsTest, Macros) { addFile("foo.cpp", R"cpp( #define MACRO X )cpp"); // LSP's SymbolKind doesn't have a "Macro" kind, and // indexSymbolKindToSymbolKind() currently maps macros // to SymbolKind::String. EXPECT_THAT(getSymbols("macro"), ElementsAre(AllOf(QName("MACRO"), WithKind(SymbolKind::String)))); } TEST_F(WorkspaceSymbolsTest, NoLocals) { addFile("foo.cpp", R"cpp( void test(int FirstParam, int SecondParam) { struct LocalClass {}; int local_var; })cpp"); EXPECT_THAT(getSymbols("l"), IsEmpty()); EXPECT_THAT(getSymbols("p"), IsEmpty()); } TEST_F(WorkspaceSymbolsTest, Globals) { addFile("foo.h", R"cpp( int global_var;