@@ -747,6 +747,109 @@ TEST_P(ByteStringTest, EndsWith) {
747747 GetMediumOrLargeCord ().size () - kSmallByteStringCapacity )));
748748}
749749
750+ TEST_P (ByteStringTest, Find) {
751+ ByteString byte_string = ByteString (GetAllocator (), GetMediumStringView ());
752+ // Find string_view
753+ EXPECT_THAT (byte_string.Find (" A string" ), Optional (0 ));
754+ EXPECT_THAT (
755+ byte_string.Find (" small string optimization!" ),
756+ Optional (GetMediumStringView ().find (" small string optimization!" )));
757+ EXPECT_THAT (byte_string.Find (" not found" ), Eq (absl::nullopt ));
758+ EXPECT_THAT (byte_string.Find (" " ), Optional (0 ));
759+ EXPECT_THAT (byte_string.Find (" " , 3 ), Optional (3 ));
760+ EXPECT_THAT (byte_string.Find (" A string" , 1 ), Eq (absl::nullopt ));
761+ // Find cord
762+ EXPECT_THAT (byte_string.Find (absl::Cord (" A string" )), Optional (0 ));
763+ EXPECT_THAT (
764+ byte_string.Find (absl::Cord (" small string optimization!" )),
765+ Optional (GetMediumStringView ().find (" small string optimization!" )));
766+ EXPECT_THAT (
767+ byte_string.Find (absl::MakeFragmentedCord (
768+ {" A string" , " that is too large for the small string optimization!" ,
769+ " extra" })),
770+ Eq (absl::nullopt ));
771+ EXPECT_THAT (byte_string.Find (GetMediumOrLargeFragmentedCord ()), Optional (0 ));
772+ EXPECT_THAT (byte_string.Find (absl::Cord (" not found" )), Eq (absl::nullopt ));
773+ }
774+
775+ TEST_P (ByteStringTest, Substring) {
776+ // small byte_string substring
777+ ByteString small_byte_string =
778+ ByteString (GetAllocator (), GetSmallStringView ());
779+ EXPECT_EQ (small_byte_string.Substring (1 , 5 ),
780+ GetSmallStringView ().substr (1 , 4 ));
781+ EXPECT_EQ (small_byte_string.Substring (0 , small_byte_string.size ()),
782+ GetSmallStringView ());
783+ EXPECT_EQ (small_byte_string.Substring (1 , 1 ), " " );
784+ // medium byte_string substring
785+ ByteString medium_byte_string =
786+ ByteString (GetAllocator (), GetMediumStringView ());
787+ EXPECT_EQ (medium_byte_string.Substring (2 , 12 ),
788+ GetMediumStringView ().substr (2 , 10 ));
789+ EXPECT_EQ (medium_byte_string.Substring (0 , medium_byte_string.size ()),
790+ GetMediumStringView ());
791+ // large byte_string substring
792+ ByteString large_byte_string =
793+ ByteString (GetAllocator (), GetMediumOrLargeCord ());
794+ EXPECT_EQ (large_byte_string.Substring (3 , 15 ),
795+ GetMediumOrLargeCord ().Subcord (3 , 12 ));
796+ EXPECT_EQ (large_byte_string.Substring (0 , large_byte_string.size ()),
797+ GetMediumOrLargeCord ());
798+ // substring with one parameter
799+ ByteString tacocat_byte_string = ByteString (GetAllocator (), " tacocat" );
800+ EXPECT_EQ (tacocat_byte_string.Substring (4 ), " cat" );
801+ }
802+
803+ TEST_P (ByteStringTest, FindEdgeCases) {
804+ ByteString empty_byte_string (GetAllocator (), " " );
805+ EXPECT_THAT (empty_byte_string.Find (" a" ), Eq (absl::nullopt ));
806+ EXPECT_THAT (empty_byte_string.Find (" " ), Optional (0 ));
807+ ByteString byte_string = ByteString (GetAllocator (), GetMediumStringView ());
808+ // Needle longer than haystack.
809+ EXPECT_THAT (byte_string.Find (std::string (byte_string.size () + 1 , ' a' )),
810+ Eq (absl::nullopt ));
811+ // Needle at the end.
812+ absl::string_view suffix = " optimization!" ;
813+ EXPECT_THAT (byte_string.Find (suffix),
814+ Optional (byte_string.size () - suffix.size ()));
815+ // pos at the end.
816+ EXPECT_THAT (byte_string.Find (" a" , byte_string.size ()), Eq (absl::nullopt ));
817+ EXPECT_THAT (byte_string.Find (" " , byte_string.size ()),
818+ Optional (byte_string.size ()));
819+ // Search in a cord-backed ByteString.
820+ ByteString cord_byte_string (GetAllocator (), GetMediumOrLargeFragmentedCord ());
821+ EXPECT_THAT (cord_byte_string.Find (" string that is too large" ),
822+ Optional (GetMediumStringView ().find (" string that is too large" )));
823+ EXPECT_THAT (cord_byte_string.Find (
824+ absl::MakeFragmentedCord ({" string that " , " is too large" })),
825+ Optional (GetMediumStringView ().find (" string that is too large" )));
826+ // Fragmented needle with empty first chunk.
827+ absl::Cord fragmented_with_empty_chunk;
828+ fragmented_with_empty_chunk.Append (" " );
829+ fragmented_with_empty_chunk.Append (" A string" );
830+ EXPECT_THAT (byte_string.Find (fragmented_with_empty_chunk), Optional (0 ));
831+ }
832+
833+ TEST_P (ByteStringTest, SubstringEdgeCases) {
834+ ByteString byte_string = ByteString (GetAllocator (), GetSmallStringView ());
835+ EXPECT_EQ (byte_string.Substring (byte_string.size (), byte_string.size ()), " " );
836+ EXPECT_EQ (byte_string.Substring (0 , 0 ), " " );
837+ }
838+
839+ #ifndef NDEBUG
840+ TEST_P (ByteStringTest, FindOutOfBounds) {
841+ ByteString byte_string = ByteString (GetAllocator (), " test" );
842+ EXPECT_DEATH (byte_string.Find (" t" , 5 ), _);
843+ }
844+
845+ TEST_P (ByteStringTest, SubstringOutOfBounds) {
846+ ByteString byte_string = ByteString (GetAllocator (), " test" );
847+ EXPECT_DEATH (static_cast <void >(byte_string.Substring (5 , 5 )), _);
848+ EXPECT_DEATH (static_cast <void >(byte_string.Substring (0 , 5 )), _);
849+ EXPECT_DEATH (static_cast <void >(byte_string.Substring (3 , 2 )), _);
850+ }
851+ #endif
852+
750853TEST_P (ByteStringTest, RemovePrefixSmall) {
751854 ByteString byte_string = ByteString (GetAllocator (), GetSmallStringView ());
752855 byte_string.RemovePrefix (1 );
0 commit comments