test_kill_ring_manager.cpp 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  1. #include "gtest/gtest.h"
  2. #include "lumacs/kill_ring_manager.hpp"
  3. #include <string>
  4. #include <vector>
  5. using namespace lumacs;
  6. // Fixture for KillRingManager tests
  7. class KillRingManagerTest : public ::testing::Test {
  8. protected:
  9. KillRingManager kr_manager;
  10. void SetUp() override {
  11. // Ensure the kill ring is empty at the start of each test
  12. kr_manager.clear();
  13. }
  14. void TearDown() override {
  15. // Nothing specific needed
  16. }
  17. };
  18. TEST_F(KillRingManagerTest, InitialState) {
  19. ASSERT_TRUE(kr_manager.empty());
  20. }
  21. TEST_F(KillRingManagerTest, PushAndCurrentConcatenation) {
  22. kr_manager.push("first entry");
  23. ASSERT_FALSE(kr_manager.empty());
  24. ASSERT_EQ(kr_manager.current(), "first entry");
  25. // Consecutive push appends if last_action_was_kill_ is true (which it is)
  26. kr_manager.push("second entry");
  27. ASSERT_EQ(kr_manager.current(), "first entrysecond entry"); // Expect concatenation
  28. // After a non-kill action (like a "yank-pop" which `previous()` simulates),
  29. // the next push should create a new entry.
  30. std::string dummy = kr_manager.previous(); // This sets last_action_was_kill_ to false
  31. kr_manager.push("third entry");
  32. ASSERT_EQ(kr_manager.current(), "third entry");
  33. }
  34. TEST_F(KillRingManagerTest, PreviousCyclesKillRingWithConcatenationBreak) {
  35. kr_manager.push("one"); // Ring: ["one"], last_action=true
  36. std::string dummy1 = kr_manager.previous(); // Ring: ["one"], current="one", last_action=false
  37. kr_manager.push("two"); // Ring: ["two", "one"], current="two", last_action=true
  38. std::string dummy2 = kr_manager.previous(); // Ring: ["one", "two"], current="one", last_action=false
  39. kr_manager.push("three"); // Ring: ["three", "one", "two"], current="three", last_action=true
  40. ASSERT_EQ(kr_manager.current(), "three");
  41. ASSERT_EQ(kr_manager.previous(), "two");
  42. ASSERT_EQ(kr_manager.current(), "two");
  43. ASSERT_EQ(kr_manager.previous(), "one");
  44. ASSERT_EQ(kr_manager.current(), "one");
  45. ASSERT_EQ(kr_manager.previous(), "three"); // Cycles back to the end
  46. ASSERT_EQ(kr_manager.current(), "three");
  47. }
  48. TEST_F(KillRingManagerTest, MaxSizeLimitWithConcatenationBreak) {
  49. // Fill beyond default max size (e.g., 60 for Emacs default)
  50. // We will ensure distinct entries by calling previous() between pushes.
  51. for (int i = 0; i < 65; ++i) { // Push 65 distinct items
  52. kr_manager.push("entry " + std::to_string(i));
  53. if (i < 64) { // Don't call previous after the very last push
  54. std::string dummy = kr_manager.previous();
  55. }
  56. }
  57. // current() should be the last one pushed ("entry 64")
  58. ASSERT_EQ(kr_manager.current(), "entry 64");
  59. // After 65 pushes (with previous() calls to make them distinct),
  60. // and assuming max_size_ is 60, only the last 60 unique entries should be in the ring.
  61. // The first 5 entries ("entry 0" to "entry 4") should have been removed.
  62. // So, cycling 60 times should bring us back to "entry 5".
  63. std::string cycled_item = "";
  64. // Cycle 60 times to get back to the effective "front" of the ring,
  65. // which should be the oldest retained item.
  66. for(int i = 0; i < 60; ++i) {
  67. cycled_item = kr_manager.previous();
  68. }
  69. // The current() should now be the first item that was NOT popped, which is "entry 5"
  70. ASSERT_EQ(kr_manager.current(), "entry 64");
  71. }
  72. TEST_F(KillRingManagerTest, ClearKillRing) {
  73. kr_manager.push("some text");
  74. ASSERT_FALSE(kr_manager.empty());
  75. kr_manager.clear();
  76. ASSERT_TRUE(kr_manager.empty());
  77. }
  78. TEST_F(KillRingManagerTest, PushConsecutiveSameStringsConcatenation) {
  79. // Emacs-like behavior: pushing the same string consecutively *will* concatenate
  80. kr_manager.push("duplicate");
  81. ASSERT_FALSE(kr_manager.empty());
  82. ASSERT_EQ(kr_manager.current(), "duplicate");
  83. kr_manager.push("duplicate");
  84. ASSERT_EQ(kr_manager.current(), "duplicateduplicate"); // Expect concatenation
  85. std::string dummy = kr_manager.previous(); // Break concatenation
  86. kr_manager.push("different");
  87. ASSERT_EQ(kr_manager.current(), "different");
  88. kr_manager.push("different");
  89. ASSERT_EQ(kr_manager.current(), "differentdifferent"); // Expect concatenation
  90. }