diff options
Diffstat (limited to 'tests/auto/corelib/text/qbytearray')
-rw-r--r-- | tests/auto/corelib/text/qbytearray/.gitattributes | 1 | ||||
-rw-r--r-- | tests/auto/corelib/text/qbytearray/CMakeLists.txt | 29 | ||||
-rw-r--r-- | tests/auto/corelib/text/qbytearray/android_testdata.qrc | 5 | ||||
-rw-r--r-- | tests/auto/corelib/text/qbytearray/rfc3252.txt | 899 | ||||
-rw-r--r-- | tests/auto/corelib/text/qbytearray/tst_qbytearray.cpp | 1418 | ||||
-rw-r--r-- | tests/auto/corelib/text/qbytearray/tst_qbytearray_mac.mm | 33 |
6 files changed, 758 insertions, 1627 deletions
diff --git a/tests/auto/corelib/text/qbytearray/.gitattributes b/tests/auto/corelib/text/qbytearray/.gitattributes deleted file mode 100644 index e04709aa2e..0000000000 --- a/tests/auto/corelib/text/qbytearray/.gitattributes +++ /dev/null @@ -1 +0,0 @@ -rfc3252.txt -crlf diff --git a/tests/auto/corelib/text/qbytearray/CMakeLists.txt b/tests/auto/corelib/text/qbytearray/CMakeLists.txt index bc07b2e1af..34307d9d44 100644 --- a/tests/auto/corelib/text/qbytearray/CMakeLists.txt +++ b/tests/auto/corelib/text/qbytearray/CMakeLists.txt @@ -1,18 +1,21 @@ -# Generated from qbytearray.pro. +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause ##################################################################### ## tst_qbytearray Test: ##################################################################### -# Collect test data -list(APPEND test_data "rfc3252.txt") +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qbytearray LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() qt_internal_add_test(tst_qbytearray SOURCES tst_qbytearray.cpp - PUBLIC_LIBRARIES + LIBRARIES Qt::CorePrivate - TESTDATA ${test_data} ) ## Scopes: @@ -21,20 +24,6 @@ qt_internal_add_test(tst_qbytearray qt_internal_extend_target(tst_qbytearray CONDITION APPLE SOURCES tst_qbytearray_mac.mm - PUBLIC_LIBRARIES + LIBRARIES ${FWFoundation} ) - -if(ANDROID AND NOT ANDROID_EMBEDDED) - # Resources: - set(android_testdata_resource_files - "rfc3252.txt" - ) - - qt_internal_add_resource(tst_qbytearray "android_testdata" - PREFIX - "/" - FILES - ${android_testdata_resource_files} - ) -endif() diff --git a/tests/auto/corelib/text/qbytearray/android_testdata.qrc b/tests/auto/corelib/text/qbytearray/android_testdata.qrc deleted file mode 100644 index 5d42f0f627..0000000000 --- a/tests/auto/corelib/text/qbytearray/android_testdata.qrc +++ /dev/null @@ -1,5 +0,0 @@ -<RCC> - <qresource prefix="/"> - <file>rfc3252.txt</file> - </qresource> -</RCC> diff --git a/tests/auto/corelib/text/qbytearray/rfc3252.txt b/tests/auto/corelib/text/qbytearray/rfc3252.txt deleted file mode 100644 index b80c61bf0a..0000000000 --- a/tests/auto/corelib/text/qbytearray/rfc3252.txt +++ /dev/null @@ -1,899 +0,0 @@ - - - - - - -Network Working Group H. Kennedy -Request for Comments: 3252 Mimezine -Category: Informational 1 April 2002 - - - Binary Lexical Octet Ad-hoc Transport - -Status of this Memo - - This memo provides information for the Internet community. It does - not specify an Internet standard of any kind. Distribution of this - memo is unlimited. - -Copyright Notice - - Copyright (C) The Internet Society (2002). All Rights Reserved. - -Abstract - - This document defines a reformulation of IP and two transport layer - protocols (TCP and UDP) as XML applications. - -1. Introduction - -1.1. Overview - - This document describes the Binary Lexical Octet Ad-hoc Transport - (BLOAT): a reformulation of a widely-deployed network-layer protocol - (IP [RFC791]), and two associated transport layer protocols (TCP - [RFC793] and UDP [RFC768]) as XML [XML] applications. It also - describes methods for transporting BLOAT over Ethernet and IEEE 802 - networks as well as encapsulating BLOAT in IP for gatewaying BLOAT - across the public Internet. - -1.2. Motivation - - The wild popularity of XML as a basis for application-level protocols - such as the Blocks Extensible Exchange Protocol [RFC3080], the Simple - Object Access Protocol [SOAP], and Jabber [JABBER] prompted - investigation into the possibility of extending the use of XML in the - protocol stack. Using XML at both the transport and network layer in - addition to the application layer would provide for an amazing amount - of power and flexibility while removing dependencies on proprietary - and hard-to-understand binary protocols. This protocol unification - would also allow applications to use a single XML parser for all - aspects of their operation, eliminating developer time spent figuring - out the intricacies of each new protocol, and moving the hard work of - - - - -Kennedy Informational [Page 1] - -RFC 3252 Binary Lexical Octet Ad-hoc Transport 1 April 2002 - - - parsing to the XML toolset. The use of XML also mitigates concerns - over "network vs. host" byte ordering which is at the root of many - network application bugs. - -1.3. Relation to Existing Protocols - - The reformulations specified in this RFC follow as closely as - possible the spirit of the RFCs on which they are based, and so MAY - contain elements or attributes that would not be needed in a pure - reworking (e.g. length attributes, which are implicit in XML.) - - The layering of network and transport protocols are maintained in - this RFC despite the optimizations that could be made if the line - were somewhat blurred (i.e. merging TCP and IP into a single, larger - element in the DTD) in order to foster future use of this protocol as - a basis for reformulating other protocols (such as ICMP.) - - Other than the encoding, the behavioral aspects of each of the - existing protocols remain unchanged. Routing, address spaces, TCP - congestion control, etc. behave as specified in the extant standards. - Adapting to new standards and experimental algorithm heuristics for - improving performance will become much easier once the move to BLOAT - has been completed. - -1.4. Requirement Levels - - The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", - "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this - document are to be interpreted as described in BCP 14, RFC 2119 - [RFC2119]. - -2. IPoXML - - This protocol MUST be implemented to be compliant with this RFC. - IPoXML is the root protocol REQUIRED for effective use of TCPoXML - (section 3.) and higher-level application protocols. - - The DTD for this document type can be found in section 7.1. - - The routing of IPoXML can be easily implemented on hosts with an XML - parser, as the regular structure lends itself handily to parsing and - validation of the document/datagram and then processing the - destination address, TTL, and checksum before sending it on to its - next-hop. - - The reformulation of IPv4 was chosen over IPv6 [RFC2460] due to the - wider deployment of IPv4 and the fact that implementing IPv6 as XML - would have exceeded the 1500 byte Ethernet MTU. - - - -Kennedy Informational [Page 2] - -RFC 3252 Binary Lexical Octet Ad-hoc Transport 1 April 2002 - - - All BLOAT implementations MUST use - and specify - the UTF-8 encoding - of RFC 2279 [RFC2279]. All BLOAT document/datagrams MUST be well- - formed and include the XMLDecl. - -2.1. IP Description - - A number of items have changed (for the better) from the original IP - specification. Bit-masks, where present have been converted into - human-readable values. IP addresses are listed in their dotted- - decimal notation [RFC1123]. Length and checksum values are present - as decimal integers. - - To calculate the length and checksum fields of the IP element, a - canonicalized form of the element MUST be used. The canonical form - SHALL have no whitespace (including newline characters) between - elements and only one space character between attributes. There - SHALL NOT be a space following the last attribute in an element. - - An iterative method SHOULD be used to calculate checksums, as the - length field will vary based on the size of the checksum. - - The payload element bears special attention. Due to the character - set restrictions of XML, the payload of IP datagrams (which MAY - contain arbitrary data) MUST be encoded for transport. This RFC - REQUIRES the contents of the payload to be encoded in the base-64 - encoding of RFC 2045 [RFC2045], but removes the requirement that the - encoded output MUST be wrapped on 76-character lines. - - - - - - - - - - - - - - - - - - - - - - - - -Kennedy Informational [Page 3] - -RFC 3252 Binary Lexical Octet Ad-hoc Transport 1 April 2002 - - -2.2. Example Datagram - - The following is an example IPoXML datagram with an empty payload: - - <?xml version="1.0" encoding="UTF-8"?> - <!DOCTYPE ip PUBLIC "-//IETF//DTD BLOAT 1.0 IP//EN" "bloat.dtd"> - <ip> - <header length="474"> - <version value="4"/> - <tos precedence="Routine" delay="Normal" throughput="Normal" - relibility="Normal" reserved="0"/> - <total.length value="461"/> - <id value="1"/> - <flags reserved="0" df="dont" mf="last"/> - <offset value="0"/> - <ttl value="255"/> - <protocol value="6"/> - <checksum value="8707"/> - <source address="10.0.0.22"/> - <destination address="10.0.0.1"/> - <options> - <end copied="0" class="0" number="0"/> - </options> - <padding pad="0"/> - </header> - <payload> - </payload> - </ip> - -3. TCPoXML - - This protocol MUST be implemented to be compliant with this RFC. The - DTD for this document type can be found in section 7.2. - -3.1. TCP Description - - A number of items have changed from the original TCP specification. - Bit-masks, where present have been converted into human-readable - values. Length and checksum and port values are present as decimal - integers. - - To calculate the length and checksum fields of the TCP element, a - canonicalized form of the element MUST be used as in section 2.1. - - An iterative method SHOULD be used to calculate checksums as in - section 2.1. - - The payload element MUST be encoded as in section 2.1. - - - -Kennedy Informational [Page 4] - -RFC 3252 Binary Lexical Octet Ad-hoc Transport 1 April 2002 - - - The TCP offset element was expanded to a maximum of 255 from 16 to - allow for the increased size of the header in XML. - - TCPoXML datagrams encapsulated by IPoXML MAY omit the <?xml?> header - as well as the <!DOCTYPE> declaration. - -3.2. Example Datagram - - The following is an example TCPoXML datagram with an empty payload: - - <?xml version="1.0" encoding="UTF-8"?> - <!DOCTYPE tcp PUBLIC "-//IETF//DTD BLOAT 1.0 TCP//EN" "bloat.dtd"> - <tcp> - <tcp.header> - <src port="31415"/> - <dest port="42424"/> - <sequence number="322622954"/> - <acknowledgement number="689715995"/> - <offset number=""/> - <reserved value="0"/> - <control syn="1" ack="1"/> - <window size="1"/> - <urgent pointer="0"/> - <checksum value="2988"/> - <tcp.options> - <tcp.end kind="0"/> - </tcp.options> - <padding pad="0"/> - </tcp.header> - <payload> - </payload> - </tcp> - -4. UDPoXML - - This protocol MUST be implemented to be compliant with this RFC. The - DTD for this document type can be found in section 7.3. - -4.1. UDP Description - - A number of items have changed from the original UDP specification. - Bit-masks, where present have been converted into human-readable - values. Length and checksum and port values are present as decimal - integers. - - - - - - - -Kennedy Informational [Page 5] - -RFC 3252 Binary Lexical Octet Ad-hoc Transport 1 April 2002 - - - To calculate the length and checksum fields of the UDP element, a - canonicalized form of the element MUST be used as in section 2.1. An - iterative method SHOULD be used to calculate checksums as in section - 2.1. - - The payload element MUST be encoded as in section 2.1. - - UDPoXML datagrams encapsulated by IPoXML MAY omit the <?xml?> header - as well as the <!DOCTYPE> declaration. - -4.2. Example Datagram - - The following is an example UDPoXML datagram with an empty payload: - - <?xml version="1.0" encoding="UTF-8"?> - <!DOCTYPE udp PUBLIC "-//IETF//DTD BLOAT 1.0 UDP//EN" "bloat.dtd"> - <udp> - <udp.header> - <src port="31415"/> - <dest port="42424"/> - <udp.length value="143"/> - <checksum value="2988"/> - </udp.header> - <payload> - </payload> - </udp> - -5. Network Transport - - This document provides for the transmission of BLOAT datagrams over - two common families of physical layer transport. Future RFCs will - address additional transports as routing vendors catch up to the - specification, and we begin to see BLOAT routed across the Internet - backbone. - -5.1. Ethernet - - BLOAT is encapsulated in Ethernet datagrams as in [RFC894] with the - exception that the type field of the Ethernet frame MUST contain the - value 0xBEEF. The first 5 octets of the Ethernet frame payload will - be 0x3c 3f 78 6d 6c ("<?xml".) - -5.2. IEEE 802 - - BLOAT is encapsulated in IEEE 802 Networks as in [RFC1042] except - that the protocol type code for IPoXML is 0xBEEF. - - - - - -Kennedy Informational [Page 6] - -RFC 3252 Binary Lexical Octet Ad-hoc Transport 1 April 2002 - - -6. Gatewaying over IP - - In order to facilitate the gradual introduction of BLOAT into the - public Internet, BLOAT MAY be encapsulated in IP as in [RFC2003] to - gateway between networks that run BLOAT natively on their LANs. - -7. DTDs - - The Transport DTDs (7.2. and 7.3.) build on the definitions in the - Network DTD (7.1.) - - The DTDs are referenced by their PubidLiteral and SystemLiteral (from - [XML]) although it is understood that most IPoXML implementations - will not need to pull down the DTD, as it will normally be embedded - in the implementation, and presents something of a catch-22 if you - need to load part of your network protocol over the network. - -7.1. IPoXML DTD - - <!-- - DTD for IP over XML. - Refer to this DTD as: - - <!DOCTYPE ip PUBLIC "-//IETF//DTD BLOAT 1.0 IP//EN" "bloat.dtd"> - --> - <!-- - DTD data types: - - Digits [0..9]+ - - Precedence "NetworkControl | InternetworkControl | - CRITIC | FlashOverride | Flash | Immediate | - Priority | Routine" - - IP4Addr "dotted-decimal" notation of [RFC1123] - - Class [0..3] - - Sec "Unclassified | Confidential | EFTO | MMMM | PROG | - Restricted | Secret | Top Secret | Reserved" - - Compartments [0..65535] - - Handling [0..65535] - - TCC [0..16777216] - - --> - - - -Kennedy Informational [Page 7] - -RFC 3252 Binary Lexical Octet Ad-hoc Transport 1 April 2002 - - - <!ENTITY % Digits "CDATA"> - <!ENTITY % Precedence "CDATA"> - <!ENTITY % IP4Addr "CDATA"> - <!ENTITY % Class "CDATA"> - <!ENTITY % Sec "CDATA"> - <!ENTITY % Compartments "CDATA"> - <!ENTITY % Handling "CDATA"> - <!ENTITY % TCC "CDATA"> - - <!ELEMENT ip (header, payload)> - - <!ELEMENT header (version, tos, total.length, id, flags, offset, ttl, - protocol, checksum, source, destination, options, - padding)> - <!-- length of header in 32-bit words --> - <!ATTLIST header - length %Digits; #REQUIRED> - - <!ELEMENT version EMPTY> - <!-- ip version. SHOULD be "4" --> - <!ATTLIST version - value %Digits; #REQUIRED> - - <!ELEMENT tos EMPTY> - <!ATTLIST tos - precedence %Precedence; #REQUIRED - delay (normal | low) #REQUIRED - throughput (normal | high) #REQUIRED - relibility (normal | high) #REQUIRED - reserved CDATA #FIXED "0"> - - <!ELEMENT total.length EMPTY> - <!-- - total length of datagram (header and payload) in octets, MUST be - less than 65,535 (and SHOULD be less than 1024 for IPoXML on local - ethernets). - --> - <!ATTLIST total.length - value %Digits; #REQUIRED> - - <!ELEMENT id EMPTY> - <!-- 0 <= id <= 65,535 --> - <!ATTLIST id - value %Digits; #REQUIRED> - - <!ELEMENT flags EMPTY> - <!-- df = don't fragment, mf = more fragments --> - <!ATTLIST flags - - - -Kennedy Informational [Page 8] - -RFC 3252 Binary Lexical Octet Ad-hoc Transport 1 April 2002 - - - reserved CDATA #FIXED "0" - df (may|dont) #REQUIRED - mf (last|more) #REQUIRED> - - <!ELEMENT offset EMPTY> - <!-- 0 <= offset <= 8192 measured in 8 octet (64-bit) chunks --> - <!ATTLIST offset - value %Digits; #REQUIRED> - - <!ELEMENT ttl EMPTY> - <!-- 0 <= ttl <= 255 --> - <!ATTLIST ttl - value %Digits; #REQUIRED> - - <!ELEMENT protocol EMPTY> - <!-- 0 <= protocol <= 255 (per IANA) --> - <!ATTLIST protocol - value %Digits; #REQUIRED> - - <!ELEMENT checksum EMPTY> - <!-- 0 <= checksum <= 65535 (over header only) --> - <!ATTLIST checksum - value %Digits; #REQUIRED> - - <!ELEMENT source EMPTY> - <!ATTLIST source - address %IP4Addr; #REQUIRED> - - <!ELEMENT destination EMPTY> - <!ATTLIST destination - address %IP4Addr; #REQUIRED> - - <!ELEMENT options ( end | noop | security | loose | strict | record - | stream | timestamp )*> - - <!ELEMENT end EMPTY> - <!ATTLIST end - copied (0|1) #REQUIRED - class CDATA #FIXED "0" - number CDATA #FIXED "0"> - - <!ELEMENT noop EMPTY> - <!ATTLIST noop - copied (0|1) #REQUIRED - class CDATA #FIXED "0" - number CDATA #FIXED "1"> - - <!ELEMENT security EMPTY> - - - -Kennedy Informational [Page 9] - -RFC 3252 Binary Lexical Octet Ad-hoc Transport 1 April 2002 - - - <!ATTLIST security - copied CDATA #FIXED "1" - class CDATA #FIXED "0" - number CDATA #FIXED "2" - length CDATA #FIXED "11" - security %Sec; #REQUIRED - compartments %Compartments; #REQUIRED - handling %Handling; #REQUIRED - tcc %TCC; #REQUIRED> - <!ELEMENT loose (hop)+> - <!ATTLIST loose - copied CDATA #FIXED "1" - class CDATA #FIXED "0" - number CDATA #FIXED "3" - length %Digits; #REQUIRED - pointer %Digits; #REQUIRED> - - <!ELEMENT hop EMPTY> - <!ATTLIST hop - address %IP4Addr; #REQUIRED> - - <!ELEMENT strict (hop)+> - <!ATTLIST strict - copied CDATA #FIXED "1" - class CDATA #FIXED "0" - number CDATA #FIXED "9" - length %Digits; #REQUIRED - pointer %Digits; #REQUIRED> - - <!ELEMENT record (hop)+> - <!ATTLIST record - copied CDATA #FIXED "0" - class CDATA #FIXED "0" - number CDATA #FIXED "7" - length %Digits; #REQUIRED - pointer %Digits; #REQUIRED> - - <!ELEMENT stream EMPTY> - <!-- 0 <= id <= 65,535 --> - <!ATTLIST stream - copied CDATA #FIXED "1" - class CDATA #FIXED "0" - number CDATA #FIXED "8" - length CDATA #FIXED "4" - id %Digits; #REQUIRED> - - <!ELEMENT timestamp (tstamp)+> - <!-- 0 <= oflw <=15 --> - - - -Kennedy Informational [Page 10] - -RFC 3252 Binary Lexical Octet Ad-hoc Transport 1 April 2002 - - - <!ATTLIST timestamp - copied CDATA #FIXED "0" - class CDATA #FIXED "2" - number CDATA #FIXED "4" - length %Digits; #REQUIRED - pointer %Digits; #REQUIRED - oflw %Digits; #REQUIRED - flag (0 | 1 | 3) #REQUIRED> - - <!ELEMENT tstamp EMPTY> - <!ATTLIST tstamp - time %Digits; #REQUIRED - address %IP4Addr; #IMPLIED> - <!-- - padding to bring header to 32-bit boundary. - pad MUST be "0"* - --> - <!ELEMENT padding EMPTY> - <!ATTLIST padding - pad CDATA #REQUIRED> - - <!-- payload MUST be encoded as base-64 [RFC2045], as modified - by section 2.1 of this RFC --> - <!ELEMENT payload (CDATA)> - -7.2. TCPoXML DTD - - <!-- - DTD for TCP over XML. - Refer to this DTD as: - - <!DOCTYPE tcp PUBLIC "-//IETF//DTD BLOAT 1.0 TCP//EN" "bloat.dtd"> - --> - - <!-- the pseudoheader is only included for checksum calculations --> - <!ELEMENT tcp (tcp.pseudoheader?, tcp.header, payload)> - - <!ELEMENT tcp.header (src, dest, sequence, acknowledgement, offset, - reserved, control, window, checksum, urgent, - tcp.options, padding)> - - <!ELEMENT src EMPTY> - <!-- 0 <= port <= 65,535 --> - <!ATTLIST src - port %Digits; #REQUIRED> - - <!ELEMENT dest EMPTY> - <!-- 0 <= port <= 65,535 --> - - - -Kennedy Informational [Page 11] - -RFC 3252 Binary Lexical Octet Ad-hoc Transport 1 April 2002 - - - <!ATTLIST dest - port %Digits; #REQUIRED> - - <!ELEMENT sequence EMPTY> - <!-- 0 <= number <= 4294967295 --> - <!ATTLIST sequence - number %Digits; #REQUIRED> - - <!ELEMENT acknowledgement EMPTY> - <!-- 0 <= number <= 4294967295 --> - <!ATTLIST acknowledgement - number %Digits; #REQUIRED> - - <!ELEMENT offset EMPTY> - <!-- 0 <= number <= 255 --> - <!ATTLIST offset - number %Digits; #REQUIRED> - - <!ELEMENT reserved EMPTY> - <!ATTLIST reserved - value CDATA #FIXED "0"> - - <!ELEMENT control EMPTY> - <!ATTLIST control - urg (0|1) #IMPLIED - ack (0|1) #IMPLIED - psh (0|1) #IMPLIED - rst (0|1) #IMPLIED - syn (0|1) #IMPLIED - fin (0|1) #IMPLIED> - - <!ELEMENT window EMPTY> - <!-- 0 <= size <= 65,535 --> - <!ATTLIST window - size %Digits; #REQUIRED> - - <!-- - checksum as in ip, but with - the following pseudo-header added into the tcp element: - --> - <!ELEMENT tcp.pseudoheader (source, destination, protocol, - tcp.length)> - - <!-- - tcp header + data length in octets. does not include the size of - - the pseudoheader. - --> - - - -Kennedy Informational [Page 12] - -RFC 3252 Binary Lexical Octet Ad-hoc Transport 1 April 2002 - - - <!ELEMENT tcp.length EMPTY> - <!ATTLIST tcp.length - value %Digits; #REQUIRED> - - <!ELEMENT urgent EMPTY> - <!-- 0 <= pointer <= 65,535 --> - <!ATTLIST urgent - pointer %Digits; #REQUIRED> - - <!ELEMENT tcp.options (tcp.end | tcp.noop | tcp.mss)+> - - <!ELEMENT tcp.end EMPTY> - <!ATTLIST tcp.end - kind CDATA #FIXED "0"> - - <!ELEMENT tcp.noop EMPTY> - <!ATTLIST tcp.noop - kind CDATA #FIXED "1"> - - <!ELEMENT tcp.mss EMPTY> - <!ATTLIST tcp.mss - kind CDATA #FIXED "2" - length CDATA #FIXED "4" - size %Digits; #REQUIRED> - -7.3. UDPoXML DTD - - <!-- - DTD for UDP over XML. - Refer to this DTD as: - - <!DOCTYPE udp PUBLIC "-//IETF//DTD BLOAT 1.0 UDP//EN" "bloat.dtd"> - --> - - <!ELEMENT udp (udp.pseudoheader?, udp.header, payload)> - - <!ELEMENT udp.header (src, dest, udp.length, checksum)> - - <!ELEMENT udp.pseudoheader (source, destination, protocol, - udp.length)> - - <!-- - udp header + data length in octets. does not include the size of - the pseudoheader. - --> - <!ELEMENT udp.length EMPTY> - <!ATTLIST udp.length - value %Digits; #REQUIRED> - - - -Kennedy Informational [Page 13] - -RFC 3252 Binary Lexical Octet Ad-hoc Transport 1 April 2002 - - -8. Security Considerations - - XML, as a subset of SGML, has the same security considerations as - specified in SGML Media Types [RFC1874]. Security considerations - that apply to IP, TCP and UDP also likely apply to BLOAT as it does - not attempt to correct for issues not related to message format. - -9. References - - [JABBER] Miller, J., "Jabber", draft-miller-jabber-00.txt, - February 2002. (Work in Progress) - - [RFC768] Postel, J., "User Datagram Protocol", STD 6, RFC 768, - August 1980. - - [RFC791] Postel, J., "Internet Protocol", STD 5, RFC 791, - September 1981. - - [RFC793] Postel, J., "Transmission Control Protocol", STD 7, RFC - 793, September 1981. - - [RFC894] Hornig, C., "Standard for the Transmission of IP - Datagrams over Ethernet Networks.", RFC 894, April 1984. - - [RFC1042] Postel, J. and J. Reynolds, "Standard for the - Transmission of IP Datagrams Over IEEE 802 Networks", STD - 43, RFC 1042, February 1988. - - [RFC1123] Braden, R., "Requirements for Internet Hosts - - Application and Support", RFC 1123, October 1989. - - [RFC1874] Levinson, E., "SGML Media Types", RFC 1874, December - 1995. - - [RFC2003] Perkins, C., "IP Encapsulation within IP", RFC 2003, - October 1996. - - [RFC2045] Freed, N. and N. Borenstein, "Multipurpose Internet Mail - Extensions (MIME) Part One: Format of Internet Message - Bodies", RFC 2045, November 1996. - - [RFC2119] Bradner, S., "Key words for use in RFCs to Indicate - Requirement Levels", BCP 14, RFC 2119, March 1997. - - [RFC2279] Yergeau, F., "UTF-8, a transformation format of ISO - 10646", RFC 2279, January 1998. - - - - - -Kennedy Informational [Page 14] - -RFC 3252 Binary Lexical Octet Ad-hoc Transport 1 April 2002 - - - [RFC2460] Deering, S. and R. Hinden, "Internet Protocol, Version 6 - (IPv6) Specification", RFC 2460, December 1998. - - [RFC3080] Rose, M., "The Blocks Extensible Exchange Protocol Core", - RFC 3080, March 2001. - - [SOAP] Box, D., Ehnebuske, D., Kakivaya, G., Layman, A., - Mendelsohn, N., Nielsen, H. F., Thatte, S. Winer, D., - "Simple Object Access Protocol (SOAP) 1.1" World Wide Web - Consortium Note, May 2000 http://www.w3.org/TR/SOAP/ - - [XML] Bray, T., Paoli, J., Sperberg-McQueen, C. M., "Extensible - Markup Language (XML)" World Wide Web Consortium - Recommendation REC- xml-19980210. - http://www.w3.org/TR/1998/REC-xml-19980210 - -10. Author's Address - - Hugh Kennedy - Mimezine - 1060 West Addison - Chicago, IL 60613 - USA - - EMail: kennedyh@engin.umich.edu - - - - - - - - - - - - - - - - - - - - - - - - - - -Kennedy Informational [Page 15] - -RFC 3252 Binary Lexical Octet Ad-hoc Transport 1 April 2002 - - -11. Full Copyright Statement - - Copyright (C) The Internet Society (2002). All Rights Reserved. - - This document and translations of it may be copied and furnished to - others, and derivative works that comment on or otherwise explain it - or assist in its implementation may be prepared, copied, published - and distributed, in whole or in part, without restriction of any - kind, provided that the above copyright notice and this paragraph are - included on all such copies and derivative works. However, this - document itself may not be modified in any way, such as by removing - the copyright notice or references to the Internet Society or other - Internet organizations, except as needed for the purpose of - developing Internet standards in which case the procedures for - copyrights defined in the Internet Standards process must be - followed, or as required to translate it into languages other than - English. - - The limited permissions granted above are perpetual and will not be - revoked by the Internet Society or its successors or assigns. - - This document and the information contained herein is provided on an - "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING - TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING - BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION - HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF - MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. - -Acknowledgement - - Funding for the RFC Editor function is currently provided by the - Internet Society. - - - - - - - - - - - - - - - - - - - -Kennedy Informational [Page 16] - diff --git a/tests/auto/corelib/text/qbytearray/tst_qbytearray.cpp b/tests/auto/corelib/text/qbytearray/tst_qbytearray.cpp index e9d0cf8236..81d79da38b 100644 --- a/tests/auto/corelib/text/qbytearray/tst_qbytearray.cpp +++ b/tests/auto/corelib/text/qbytearray/tst_qbytearray.cpp @@ -1,31 +1,6 @@ -/**************************************************************************** -** -** Copyright (C) 2020 The Qt Company Ltd. -** Copyright (C) 2016 Intel Corporation. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2022 The Qt Company Ltd. +// Copyright (C) 2016 Intel Corporation. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <QTest> @@ -35,6 +10,13 @@ #include <limits.h> #include <private/qtools_p.h> +#include "../shared/test_number_shared.h" + +#include <QtCore/q20iterator.h> +#include <sstream> + +using namespace Qt::StringLiterals; + class tst_QByteArray : public QObject { Q_OBJECT @@ -42,16 +24,10 @@ class tst_QByteArray : public QObject public: tst_QByteArray(); private slots: + // Note: much of the shared API is tested in ../qbytearrayapisymmetry/ void swap(); void qChecksum_data(); void qChecksum(); - void qCompress_data(); -#ifndef QT_NO_COMPRESS - void qCompress(); - void qUncompressCorruptedData_data(); - void qUncompressCorruptedData(); - void qCompressionZeroTermination(); -#endif void constByteArray(); void leftJustified(); void rightJustified(); @@ -75,40 +51,35 @@ private slots: void prependExtended_data(); void prependExtended(); void append(); + void appendFromRawData(); void appendExtended_data(); void appendExtended(); + void appendEmptyNull(); + void assign(); + void assignShared(); + void assignUsesPrependBuffer(); void insert(); void insertExtended_data(); void insertExtended(); void remove_data(); void remove(); + void remove_extra(); void removeIf(); + void erase(); + void erase_single_arg(); void replace_data(); void replace(); void replaceWithSpecifiedLength(); - void toLong_data(); - void toLong(); - void toULong_data(); - void toULong(); - void toLongLong_data(); - void toLongLong(); - void toULongLong_data(); - void toULongLong(); void number(); - void toShort(); - void toUShort(); - void toInt_data(); - void toInt(); - void toUInt_data(); - void toUInt(); - void toFloat(); - void toDouble_data(); - void toDouble(); + void number_double_data(); + void number_double(); + void number_base_data(); + void number_base(); + void nullness(); void blockSizeCalculations(); void resizeAfterFromRawData(); - void appendAfterFromRawData(); void toFromHex_data(); void toFromHex(); void toFromPercentEncoding(); @@ -116,8 +87,8 @@ private slots: void fromPercentEncoding(); void toPercentEncoding_data(); void toPercentEncoding(); - void toPercentEncoding2_data(); - void toPercentEncoding2(); + void pecentEncodingRoundTrip_data(); + void pecentEncodingRoundTrip(); void qstrcmp_data(); void qstrcmp(); @@ -134,8 +105,9 @@ private slots: void reserve(); void reserveExtended_data(); void reserveExtended(); - void movablity_data(); - void movablity(); + void resize(); + void movability_data(); + void movability(); void literals(); void userDefinedLiterals(); void toUpperLower_data(); @@ -151,8 +123,8 @@ private slots: void fill(); void dataPointers(); void truncate(); - void trimmed(); void trimmed_data(); + void trimmed(); void simplified(); void simplified_data(); void left(); @@ -160,6 +132,7 @@ private slots: void mid(); void length(); void length_data(); + void slice() const; }; static const QByteArray::DataPointer staticStandard = { @@ -173,6 +146,15 @@ static const QByteArray::DataPointer staticNotNullTerminated = { 4 }; +template <typename String> String detached(String s) +{ + if (!s.isNull()) { // detaching loses nullness, but we need to preserve it + auto d = s.data(); + Q_UNUSED(d); + } + return s; +} + template <class T> const T &verifyZeroTermination(const T &t) { return t; } QByteArray verifyZeroTermination(const QByteArray &ba) @@ -185,7 +167,7 @@ QByteArray verifyZeroTermination(const QByteArray &ba) if (!baDataPtr->isMutable()) return ba; - int baSize = ba.size(); + qsizetype baSize = ba.size(); char baTerminator = ba.constData()[baSize]; if ('\0' != baTerminator) return QString::fromUtf8( @@ -259,92 +241,13 @@ void tst_QByteArray::qChecksum() QFETCH(Qt::ChecksumType, standard); QFETCH(uint, checksum); - QCOMPARE(data.length(), int(len)); + QCOMPARE(data.size(), int(len)); if (standard == Qt::ChecksumIso3309) { QCOMPARE(::qChecksum(QByteArrayView(data.constData(), len)), static_cast<quint16>(checksum)); } QCOMPARE(::qChecksum(QByteArrayView(data.constData(), len), standard), static_cast<quint16>(checksum)); } -void tst_QByteArray::qCompress_data() -{ - QTest::addColumn<QByteArray>("ba"); - - const int size1 = 1024*1024; - QByteArray ba1( size1, 0 ); - - QTest::newRow( "00" ) << QByteArray(); - - int i; - for ( i=0; i<size1; i++ ) - ba1[i] = (char)( i / 1024 ); - QTest::newRow( "01" ) << ba1; - - for ( i=0; i<size1; i++ ) - ba1[i] = (char)( i % 256 ); - QTest::newRow( "02" ) << ba1; - - ba1.fill( 'A' ); - QTest::newRow( "03" ) << ba1; - - QFile file( QFINDTESTDATA("rfc3252.txt") ); - QVERIFY( file.open(QIODevice::ReadOnly) ); - QTest::newRow( "04" ) << file.readAll(); -} - -#ifndef QT_NO_COMPRESS -void tst_QByteArray::qCompress() -{ - QFETCH( QByteArray, ba ); - QByteArray compressed = ::qCompress( ba ); - QTEST( ::qUncompress( compressed ), "ba" ); -} - -void tst_QByteArray::qUncompressCorruptedData_data() -{ - QTest::addColumn<QByteArray>("in"); - - QTest::newRow("0x00000000") << QByteArray("\x00\x00\x00\x00", 4); - QTest::newRow("0x000000ff") << QByteArray("\x00\x00\x00\xff", 4); - QTest::newRow("0x3f000000") << QByteArray("\x3f\x00\x00\x00", 4); - QTest::newRow("0x3fffffff") << QByteArray("\x3f\xff\xff\xff", 4); - QTest::newRow("0x7fffff00") << QByteArray("\x7f\xff\xff\x00", 4); - QTest::newRow("0x7fffffff") << QByteArray("\x7f\xff\xff\xff", 4); - QTest::newRow("0x80000000") << QByteArray("\x80\x00\x00\x00", 4); - QTest::newRow("0x800000ff") << QByteArray("\x80\x00\x00\xff", 4); - QTest::newRow("0xcf000000") << QByteArray("\xcf\x00\x00\x00", 4); - QTest::newRow("0xcfffffff") << QByteArray("\xcf\xff\xff\xff", 4); - QTest::newRow("0xffffff00") << QByteArray("\xff\xff\xff\x00", 4); - QTest::newRow("0xffffffff") << QByteArray("\xff\xff\xff\xff", 4); -} - -// Corrupt data causes this test to lock up on HP-UX / PA-RISC with gcc, -// SOLARIS, and Windows. -// This test is expected to produce some warning messages in the test output. -void tst_QByteArray::qUncompressCorruptedData() -{ -#if !(defined(Q_OS_HPUX) && !defined(__ia64) && defined(Q_CC_GNU)) && !defined(Q_OS_SOLARIS) && !defined(Q_OS_WIN) - QFETCH(QByteArray, in); - - QByteArray res; - res = ::qUncompress(in); - QCOMPARE(res, QByteArray()); - - res = ::qUncompress(in + "blah"); - QCOMPARE(res, QByteArray()); -#else - QSKIP("This test freezes on this platform"); -#endif -} - -void tst_QByteArray::qCompressionZeroTermination() -{ - QString s = "Hello, I'm a string."; - QByteArray ba = ::qUncompress(::qCompress(s.toLocal8Bit())); - QVERIFY((int) *(ba.data() + ba.size()) == 0); -} - -#endif void tst_QByteArray::constByteArray() { @@ -425,18 +328,17 @@ void tst_QByteArray::setNum() QCOMPARE(a.setNum(37, 2), QByteArray("100101")); QCOMPARE(a.setNum(37, 36), QByteArray("11")); - // Negative numbers are only properly supported for base 10. - QCOMPARE(a.setNum(short(-1), 16), QByteArray("ffff")); - QCOMPARE(a.setNum(int(-1), 16), QByteArray("ffffffff")); - QCOMPARE(a.setNum(qlonglong(-1), 16), QByteArray("ffffffffffffffff")); + QCOMPARE(a.setNum(short(-1), 16), QByteArray("-1")); + QCOMPARE(a.setNum(int(-1), 16), QByteArray("-1")); + QCOMPARE(a.setNum(qlonglong(-1), 16), QByteArray("-1")); QCOMPARE(a.setNum(short(-1), 10), QByteArray("-1")); QCOMPARE(a.setNum(int(-1), 10), QByteArray("-1")); QCOMPARE(a.setNum(qlonglong(-1), 10), QByteArray("-1")); QCOMPARE(a.setNum(-123), QByteArray("-123")); - QCOMPARE(a.setNum(0x123,16), QByteArray("123")); - QCOMPARE(a.setNum((short)123), QByteArray("123")); + QCOMPARE(a.setNum(0x123, 16), QByteArray("123")); + QCOMPARE(a.setNum(short(123)), QByteArray("123")); QCOMPARE(a.setNum(1.23), QByteArray("1.23")); QCOMPARE(a.setNum(1.234567), QByteArray("1.23457")); @@ -536,7 +438,7 @@ void tst_QByteArray::split() QFETCH(int, size); QList<QByteArray> list = sample.split(' '); - QCOMPARE(list.count(), size); + QCOMPARE(list.size(), size); } void tst_QByteArray::swap() @@ -822,18 +724,18 @@ void tst_QByteArray::qvsnprintf() void tst_QByteArray::qstrlen() { const char *src = "Something about ... \0 a string."; - QCOMPARE(::qstrlen((char*)0), (uint)0); - QCOMPARE(::qstrlen(src), (uint)20); + QCOMPARE(::qstrlen(nullptr), size_t(0)); + QCOMPARE(::qstrlen(src), size_t(20)); } void tst_QByteArray::qstrnlen() { const char *src = "Something about ... \0 a string."; - QCOMPARE(::qstrnlen((char*)0, 1), (uint)0); - QCOMPARE(::qstrnlen(src, 31), (uint)20); - QCOMPARE(::qstrnlen(src, 19), (uint)19); - QCOMPARE(::qstrnlen(src, 21), (uint)20); - QCOMPARE(::qstrnlen(src, 20), (uint)20); + QCOMPARE(::qstrnlen(nullptr, 1), size_t(0)); + QCOMPARE(::qstrnlen(src, 31), size_t(20)); + QCOMPARE(::qstrnlen(src, 19), size_t(19)); + QCOMPARE(::qstrnlen(src, 21), size_t(20)); + QCOMPARE(::qstrnlen(src, 20), size_t(20)); } void tst_QByteArray::qstrcpy() @@ -859,7 +761,10 @@ void tst_QByteArray::qstrncpy() // src == nullptr QCOMPARE(::qstrncpy(dst.data(), 0, 0), (char*)0); + QCOMPARE(*dst.data(), 'b'); // must not have written to dst QCOMPARE(::qstrncpy(dst.data(), 0, 10), (char*)0); + QCOMPARE(*dst.data(), '\0'); // must have written to dst + *dst.data() = 'b'; // restore // valid pointers, but len == 0 QCOMPARE(::qstrncpy(dst.data(), src.data(), 0), dst.data()); @@ -976,6 +881,7 @@ void tst_QByteArray::append() QCOMPARE(QByteArray().append(2, 'a'), QByteArray("aa")); QCOMPARE(QByteArray().append(QByteArray("data")), QByteArray("data")); QCOMPARE(QByteArray().append(data), QByteArray("data")); + QCOMPARE(QByteArray().append(data, -1), QByteArray("data")); QCOMPARE(QByteArray().append(data, 2), QByteArray("da")); QCOMPARE(QByteArray().append(QByteArrayView(data)), QByteArray("data")); @@ -1019,6 +925,20 @@ void tst_QByteArray::append() } } +void tst_QByteArray::appendFromRawData() +{ + char rawData[] = "Hello World!"; + QByteArray ba = QByteArray::fromRawData(rawData, std::size(rawData) - 1); + + QByteArray copy; + copy.append(ba); + QCOMPARE(copy, ba); + // We make an _actual_ copy, because appending a byte array + // created with fromRawData() might be optimized to copy the DataPointer, + // which means we may point to temporary stack data. + QCOMPARE_NE((void *)copy.constData(), (void *)ba.constData()); +} + void tst_QByteArray::appendExtended_data() { prependExtended_data(); @@ -1043,6 +963,207 @@ void tst_QByteArray::appendExtended() QCOMPARE(array.size(), 11); } +void tst_QByteArray::appendEmptyNull() +{ + QByteArray a; + QVERIFY(a.isEmpty()); + QVERIFY(a.isNull()); + + QByteArray b(""); + QVERIFY(b.isEmpty()); + QVERIFY(!b.isNull()); + + // Concatenating a null and an empty-but-not-null byte arrays results in + // an empty but not null byte array + QByteArray r = a + b; + QVERIFY(r.isEmpty()); + QVERIFY(!r.isNull()); +} + +void tst_QByteArray::assign() +{ + // QByteArray &assign(QByteArrayView) + { + QByteArray ba; + QByteArray test("data"); + QCOMPARE(ba.assign(test), test); + QCOMPARE(ba.size(), test.size()); + test = "data\0data"; + QCOMPARE(ba.assign(test), test); + QCOMPARE(ba.size(), test.size()); + test = "data\0data"_ba; + QCOMPARE(ba.assign(test), test); + QCOMPARE(ba.size(), test.size()); + } + // QByteArray &assign(qsizetype, char); + { + QByteArray ba; + QByteArray test("ddd"); + QCOMPARE(ba.assign(3, 'd'), test); + QCOMPARE(ba.size(), test.size()); + test = "xx"; + QCOMPARE(ba.assign(20, 'd').assign(2, 'x'), test); + QCOMPARE(ba.size(), test.size()); + test = "ddddd"; + QCOMPARE(ba.assign(0, 'x').assign(5, 'd'), test); + QCOMPARE(ba.size(), test.size()); + test = "\0\0\0"_ba; + QCOMPARE(ba.assign(0, 'x').assign(3, '\0'), test); + QCOMPARE(ba.size(), test.size()); + } + // QByteArray &assign(InputIterator, InputIterator) + { + QByteArray ba; + QByteArrayView test; + + QList<char> l = {'\0', 'T', 'E', 'S', 'T'}; + ba.assign(l.begin(), l.end()); + test = "\0TEST"_ba; + QCOMPARE(ba, test); + QCOMPARE(ba.size(), test.size()); + + const std::byte bytes[] = {std::byte('T'), std::byte(0), std::byte('S'), std::byte('T')}; + test = QByteArrayView::fromArray(bytes); + QCOMPARE(ba.assign(test.begin(), test.end()), test); + QCOMPARE(ba.size(), test.size()); + + std::stringstream ss; + ss << "T " << '\0' << ' ' << "S " << "T "; + ba.assign(std::istream_iterator<char>{ss}, std::istream_iterator<char>{}); + test = "T\0ST"_ba; + QCOMPARE(ba, test); + QCOMPARE(ba.size(), test.size()); + } + // Test chaining + { + QByteArray ba; + QByteArray test("TTTTT"); + char arr[] = {'T', 'E', 'S', 'T'}; + ba.assign(std::begin(arr), std::end(arr)).assign({"Hello World!"}).assign(5, 'T'); + QCOMPARE(ba, test); + QCOMPARE(ba.size(), test.size()); + test = "DATA"; + QCOMPARE(ba.assign(300, 'T').assign({"DATA"}), test); + QCOMPARE(ba.size(), test.size()); + test = QByteArray(arr, q20::ssize(arr)); + QCOMPARE(ba.assign(10, 'c').assign(std::begin(arr), std::end(arr)), test); + QCOMPARE(ba.size(), test.size()); + test = "TTT"; + QCOMPARE(ba.assign("data").assign(QByteArrayView::fromArray( + {std::byte('T'), std::byte('T'), std::byte('T')})), test); + QCOMPARE(ba.size(), test.size()); + test = "\0data"; + QCOMPARE(ba.assign("data").assign("\0data"), test); + QCOMPARE(ba.size(), test.size()); + } +} + +void tst_QByteArray::assignShared() +{ + { + QByteArray ba; + ba.assign({"DATA"}); + QVERIFY(ba.isDetached()); + QCOMPARE(ba, QByteArray("DATA")); + + auto baCopy = ba; + QVERIFY(!ba.isDetached()); + QVERIFY(!baCopy.isDetached()); + QVERIFY(ba.isSharedWith(baCopy)); + QVERIFY(baCopy.isSharedWith(ba)); + + ba.assign(10, 'D'); + QVERIFY(ba.isDetached()); + QVERIFY(baCopy.isDetached()); + QVERIFY(!ba.isSharedWith(baCopy)); + QVERIFY(!baCopy.isSharedWith(ba)); + QCOMPARE(ba, QByteArray("DDDDDDDDDD")); + QCOMPARE(baCopy, QByteArray("DATA")); + } + { + QByteArray ba("START"); + QByteArrayView bav("DATA"); + QVERIFY(ba.isDetached()); + QCOMPARE(ba, QByteArray("START")); + + auto copyForwardIt = ba; + QVERIFY(!ba.isDetached()); + QVERIFY(!copyForwardIt.isDetached()); + QVERIFY(ba.isSharedWith(copyForwardIt)); + QVERIFY(copyForwardIt.isSharedWith(ba)); + + ba.assign(bav.begin(), bav.end()); + QVERIFY(ba.isDetached()); + QVERIFY(copyForwardIt.isDetached()); + QVERIFY(!ba.isSharedWith(copyForwardIt)); + QVERIFY(!copyForwardIt.isSharedWith(ba)); + QCOMPARE(ba, QByteArray("DATA")); + QCOMPARE(copyForwardIt, QByteArray("START")); + + auto copyInputIt = ba; + QVERIFY(!ba.isDetached()); + QVERIFY(!copyInputIt.isDetached()); + QVERIFY(ba.isSharedWith(copyInputIt)); + QVERIFY(copyInputIt.isSharedWith(ba)); + + std::stringstream ss("1 2 3 4 5 6 "); + ba.assign(std::istream_iterator<char>{ss}, std::istream_iterator<char>{}); + QVERIFY(ba.isDetached()); + QVERIFY(copyInputIt.isDetached()); + QVERIFY(!ba.isSharedWith(copyInputIt)); + QVERIFY(!copyInputIt.isSharedWith(ba)); + QCOMPARE(ba, QByteArray("123456")); + QCOMPARE(copyInputIt, QByteArray("DATA")); + } +} + +void tst_QByteArray::assignUsesPrependBuffer() +{ + const auto capBegin = [](const QByteArray &ba) { + return ba.begin() - ba.d.freeSpaceAtBegin(); + }; + const auto capEnd = [](const QByteArray &ba) { + return ba.end() + ba.d.freeSpaceAtEnd(); + }; + // QByteArray &assign(QByteArrayView) + { + QByteArray withFreeSpaceAtBegin; + for (int i = 0; i < 100 && withFreeSpaceAtBegin.d.freeSpaceAtBegin() < 2; ++i) + withFreeSpaceAtBegin.prepend("data"); + QCOMPARE_GT(withFreeSpaceAtBegin.d.freeSpaceAtBegin(), 1); + + const auto oldCapBegin = capBegin(withFreeSpaceAtBegin); + const auto oldCapEnd = capEnd(withFreeSpaceAtBegin); + + std::string test(withFreeSpaceAtBegin.d.freeSpaceAtBegin(), 'd'); + withFreeSpaceAtBegin.assign(test); + + QCOMPARE_EQ(withFreeSpaceAtBegin.d.freeSpaceAtBegin(), 0); // we used the prepend buffer + QCOMPARE_EQ(capBegin(withFreeSpaceAtBegin), oldCapBegin); + QCOMPARE_EQ(capEnd(withFreeSpaceAtBegin), oldCapEnd); + QCOMPARE(withFreeSpaceAtBegin, test.data()); + } + // QByteArray &assign(InputIterator, InputIterator) + { + QByteArray withFreeSpaceAtBegin; + for (int i = 0; i < 100 && withFreeSpaceAtBegin.d.freeSpaceAtBegin() < 2; ++i) + withFreeSpaceAtBegin.prepend("data"); + QCOMPARE_GT(withFreeSpaceAtBegin.d.freeSpaceAtBegin(), 1); + + const auto oldCapBegin = capBegin(withFreeSpaceAtBegin); + const auto oldCapEnd = capEnd(withFreeSpaceAtBegin); + + std::stringstream ss; + for (qsizetype i = 0; i < withFreeSpaceAtBegin.d.freeSpaceAtBegin(); ++i) + ss << "d "; + + withFreeSpaceAtBegin.assign(std::istream_iterator<char>{ss}, std::istream_iterator<char>{}); + QCOMPARE_EQ(withFreeSpaceAtBegin.d.freeSpaceAtBegin(), 0); // we used the prepend buffer + QCOMPARE_EQ(capBegin(withFreeSpaceAtBegin), oldCapBegin); + QCOMPARE_EQ(capEnd(withFreeSpaceAtBegin), oldCapEnd); + } +} + void tst_QByteArray::insert() { const char data[] = "data"; @@ -1179,7 +1300,30 @@ void tst_QByteArray::remove() QFETCH(int, position); QFETCH(int, length); QFETCH(QByteArray, expected); - QCOMPARE(src.remove(position, length), expected); + // Test when it's shared + QByteArray ba1 = src; + QCOMPARE(ba1.remove(position, length), expected); + + // Test when it's not shared + QByteArray ba2 = src; + ba2.detach(); + QCOMPARE(ba2.remove(position, length), expected); +} + +void tst_QByteArray::remove_extra() +{ + QByteArray ba = "Clock"; + ba.removeFirst(); + QCOMPARE(ba, "lock"); + ba.removeLast(); + QCOMPARE(ba, "loc"); + ba.removeAt(ba.indexOf('o')); + QCOMPARE(ba, "lc"); + ba.clear(); + // No crash on empty byte arrays + ba.removeFirst(); + ba.removeLast(); + ba.removeAt(2); } void tst_QByteArray::removeIf() @@ -1191,7 +1335,58 @@ void tst_QByteArray::removeIf() QVERIFY(!a.isDetached()); a = QByteArray("aBcAbC"); + // Test when it's not shared + QVERIFY(a.isDetached()); QCOMPARE(a.removeIf(removeA), QByteArray("BcbC")); + + a = QByteArray("aBcAbC"); + QByteArray b = a; + // Test when it's shared + QVERIFY(!b.isDetached()); + QCOMPARE(b.removeIf(removeA), QByteArray("BcbC")); +} + +void tst_QByteArray::erase() +{ + { + QByteArray ba = "kittens"; + auto it = ba.erase(ba.cbegin(), ba.cbegin() + 2); + QCOMPARE(ba, "ttens"); + QCOMPARE(it, ba.cbegin()); + } + + { + QByteArray ba = "kittens"; + auto it = ba.erase(ba.cbegin(), ba.cend()); + QCOMPARE(ba, ""); + QCOMPARE(it, ba.cbegin()); + QCOMPARE(ba.cbegin(), ba.cend()); + } + + { + QByteArray ba = "kite"; + auto it = ba.erase(ba.cbegin(), ba.cbegin()); + // erase() should return an iterator (not const_iterator) + *it = 'Z'; + QCOMPARE(ba, "Zite"); + QCOMPARE(it, ba.cbegin()); + } +} + +void tst_QByteArray::erase_single_arg() +{ + QByteArray ba = "abcdefg"; + ba.erase(ba.cend()); + auto it = ba.erase(ba.cbegin()); + QCOMPARE_EQ(ba, "bcdefg"); + QCOMPARE(it, ba.cbegin()); + + it = ba.erase(std::prev(ba.end())); + QCOMPARE_EQ(ba, "bcdef"); + QCOMPARE(it, ba.cend()); + + it = ba.erase(std::find(ba.begin(), ba.end(), QChar('d'))); + QCOMPARE(it, ba.begin() + 2); } void tst_QByteArray::replace_data() @@ -1283,412 +1478,139 @@ void tst_QByteArray::replaceWithSpecifiedLength() void tst_QByteArray::number() { - QCOMPARE(QString(QByteArray::number((quint64) 0)), - QString(QByteArray("0"))); - QCOMPARE(QString(QByteArray::number(Q_UINT64_C(0xFFFFFFFFFFFFFFFF))), - QString(QByteArray("18446744073709551615"))); - QCOMPARE(QString(QByteArray::number(Q_INT64_C(0xFFFFFFFFFFFFFFFF))), - QString(QByteArray("-1"))); - QCOMPARE(QString(QByteArray::number(qint64(0))), - QString(QByteArray("0"))); - QCOMPARE(QString(QByteArray::number(Q_INT64_C(0x7FFFFFFFFFFFFFFF))), - QString(QByteArray("9223372036854775807"))); - QCOMPARE(QString(QByteArray::number(Q_INT64_C(0x8000000000000000))), - QString(QByteArray("-9223372036854775808"))); + QCOMPARE(QByteArray::number(quint64(0)), QByteArray("0")); + QCOMPARE(QByteArray::number(Q_UINT64_C(0xFFFFFFFFFFFFFFFF)), + QByteArray("18446744073709551615")); + QCOMPARE(QByteArray::number(Q_INT64_C(0xFFFFFFFFFFFFFFFF)), QByteArray("-1")); + QCOMPARE(QByteArray::number(qint64(0)), QByteArray("0")); + QCOMPARE(QByteArray::number(Q_INT64_C(0x7FFFFFFFFFFFFFFF)), + QByteArray("9223372036854775807")); + QCOMPARE(QByteArray::number(Q_INT64_C(0x8000000000000000)), + QByteArray("-9223372036854775808")); } -void tst_QByteArray::toShort() +void tst_QByteArray::number_double_data() { - bool ok = true; // opposite to the next expected result - - QCOMPARE(QByteArray().toShort(&ok), 0); - QVERIFY(!ok); - - QCOMPARE(QByteArray("").toShort(&ok), 0); - QVERIFY(!ok); - - QCOMPARE(QByteArray("12345").toShort(&ok), 12345); - QVERIFY(ok); - - QCOMPARE(QByteArray("-12345").toShort(&ok), -12345); - QVERIFY(ok); - - QCOMPARE(QByteArray("32767").toShort(&ok), 32767); - QVERIFY(ok); - - QCOMPARE(QByteArray("-32768").toShort(&ok), -32768); - QVERIFY(ok); - - QCOMPARE(QByteArray("32768").toShort(&ok), 0); - QVERIFY(!ok); + QTest::addColumn<double>("value"); + QTest::addColumn<char>("format"); + QTest::addColumn<int>("precision"); + QTest::addColumn<QByteArray>("expected"); - QCOMPARE(QByteArray("-32769").toShort(&ok), 0); - QVERIFY(!ok); + // This function is implemented in ../shared/test_number_shared.h + add_number_double_shared_data([](NumberDoubleTestData datum) { + QByteArray ba(datum.expected.data(), datum.expected.size()); + const char *title = !datum.optTitle.isEmpty() ? datum.optTitle.data() : ba.data(); + QTest::addRow("%s, format '%c', precision %d", title, datum.f, datum.p) + << datum.d << datum.f << datum.p << ba; + if (datum.f != 'f') { // Also test uppercase format + datum.f = QtMiscUtils::toAsciiUpper(datum.f); + QByteArray upper = ba.toUpper(); + QByteArray upperTitle = QByteArray(title); + if (!datum.optTitle.isEmpty()) + upperTitle += ", uppercase"; + else + upperTitle = upperTitle.toUpper(); + QTest::addRow("%s, format '%c', precision %d", upperTitle.data(), datum.f, datum.p) + << datum.d << datum.f << datum.p << upper; + } + }); } -void tst_QByteArray::toUShort() +void tst_QByteArray::number_double() { - bool ok = true; // opposite to the next expected result - - QCOMPARE(QByteArray().toUShort(&ok), 0); - QVERIFY(!ok); + QFETCH(double, value); + QFETCH(char, format); + QFETCH(int, precision); - QCOMPARE(QByteArray("").toUShort(&ok), 0); - QVERIFY(!ok); - - QCOMPARE(QByteArray("12345").toUShort(&ok), 12345); - QVERIFY(ok); - - QCOMPARE(QByteArray("-12345").toUShort(&ok), 0); - QVERIFY(!ok); - - QCOMPARE(QByteArray("32767").toUShort(&ok), 32767); - QVERIFY(ok); - - QCOMPARE(QByteArray("32768").toUShort(&ok), 32768); - QVERIFY(ok); - - QCOMPARE(QByteArray("65535").toUShort(&ok), 65535); - QVERIFY(ok); - - QCOMPARE(QByteArray("65536").toUShort(&ok), 0); - QVERIFY(!ok); + if constexpr (std::numeric_limits<double>::has_denorm != std::denorm_present) { + if (::qstrcmp(QTest::currentDataTag(), "Very small number, very high precision, format 'f', precision 350") == 0) { + QSKIP("Skipping 'denorm' as this type lacks denormals on this system"); + } + } + QTEST(QByteArray::number(value, format, precision), "expected"); } -// defined later -extern const char globalChar; - -void tst_QByteArray::toInt_data() +void tst_QByteArray::number_base_data() { - QTest::addColumn<QByteArray>("string"); + QTest::addColumn<qlonglong>("n"); QTest::addColumn<int>("base"); - QTest::addColumn<int>("expectednumber"); - QTest::addColumn<bool>("expectedok"); - - QTest::newRow("null") << QByteArray() << 10 << 0 << false; - QTest::newRow("empty") << QByteArray("") << 10 << 0 << false; - - QTest::newRow("base 10") << QByteArray("100") << 10 << int(100) << true; - QTest::newRow("base 16-1") << QByteArray("100") << 16 << int(256) << true; - QTest::newRow("base 16-2") << QByteArray("0400") << 16 << int(1024) << true; - QTest::newRow("base 2") << QByteArray("1111") << 2 << int(15) << true; - QTest::newRow("base 8") << QByteArray("100") << 8 << int(64) << true; - QTest::newRow("base 0-1") << QByteArray("0x10") << 0 << int(16) << true; - QTest::newRow("base 0-2") << QByteArray("10") << 0 << int(10) << true; - QTest::newRow("base 0-3") << QByteArray("010") << 0 << int(8) << true; - QTest::newRow("empty") << QByteArray() << 0 << int(0) << false; - - QTest::newRow("leading space") << QByteArray(" 100") << 10 << int(100) << true; - QTest::newRow("trailing space") << QByteArray("100 ") << 10 << int(100) << true; - QTest::newRow("leading junk") << QByteArray("x100") << 10 << int(0) << false; - QTest::newRow("trailing junk") << QByteArray("100x") << 10 << int(0) << false; + QTest::addColumn<QByteArray>("expected"); - // using fromRawData - QTest::newRow("raw1") << QByteArray::fromRawData("1", 1) << 10 << 1 << true; - QTest::newRow("raw2") << QByteArray::fromRawData("1foo", 1) << 10 << 1 << true; - QTest::newRow("raw3") << QByteArray::fromRawData("12", 1) << 10 << 1 << true; - QTest::newRow("raw4") << QByteArray::fromRawData("123456789", 1) << 10 << 1 << true; - QTest::newRow("raw5") << QByteArray::fromRawData("123456789", 2) << 10 << 12 << true; + QTest::newRow("base 10") << 12346LL << 10 << QByteArray("12346"); + QTest::newRow("base 2") << 12346LL << 2 << QByteArray("11000000111010"); + QTest::newRow("base 8") << 12346LL << 8 << QByteArray("30072"); + QTest::newRow("base 16") << 12346LL << 16 << QByteArray("303a"); + QTest::newRow("base 17") << 12346LL << 17 << QByteArray("28c4"); + QTest::newRow("base 36") << 2181789482LL << 36 << QByteArray("102zbje"); - QTest::newRow("raw-static") << QByteArray::fromRawData(&globalChar, 1) << 10 << 1 << true; + QTest::newRow("largeint, base 10") + << 123456789012LL << 10 << QByteArray("123456789012"); + QTest::newRow("largeint, base 2") + << 123456789012LL << 2 << QByteArray("1110010111110100110010001101000010100"); + QTest::newRow("largeint, base 8") + << 123456789012LL << 8 << QByteArray("1627646215024"); + QTest::newRow("largeint, base 16") + << 123456789012LL << 16 << QByteArray("1cbe991a14"); + QTest::newRow("largeint, base 17") + << 123456789012LL << 17 << QByteArray("10bec2b629"); } -void tst_QByteArray::toInt() +void tst_QByteArray::number_base() { - QFETCH( QByteArray, string ); + QFETCH( qlonglong, n ); QFETCH( int, base ); - QFETCH( int, expectednumber ); - QFETCH( bool, expectedok ); - - bool ok; - int number = string.toInt(&ok, base); - - QCOMPARE( ok, expectedok ); - QCOMPARE( number, expectednumber ); -} - -void tst_QByteArray::toUInt_data() -{ - QTest::addColumn<QByteArray>("string"); - QTest::addColumn<int>("base"); - QTest::addColumn<uint>("expectednumber"); - QTest::addColumn<bool>("expectedok"); - - QTest::newRow("null") << QByteArray() << 10 << 0u << false; - QTest::newRow("empty") << QByteArray("") << 10 << 0u << false; - - QTest::newRow("negative value") << QByteArray("-50") << 10 << 0u << false; - QTest::newRow("more than MAX_INT") << QByteArray("3234567890") << 10 << 3234567890u << true; - QTest::newRow("2^32 - 1") << QByteArray("4294967295") << 10 << 4294967295u << true; - if (sizeof(int) == 4) - QTest::newRow("2^32") << QByteArray("4294967296") << 10 << 0u << false; -} - -void tst_QByteArray::toUInt() -{ - QFETCH(QByteArray, string); - QFETCH(int, base); - QFETCH(uint, expectednumber); - QFETCH(bool, expectedok); - - bool ok; - const uint number = string.toUInt(&ok, base); - - QCOMPARE(ok, expectedok); - QCOMPARE(number, expectednumber); -} - -void tst_QByteArray::toFloat() -{ - bool ok = true; // opposite to the next expected result - - QCOMPARE(QByteArray().toFloat(&ok), 0.0f); - QVERIFY(!ok); - - QCOMPARE(QByteArray("").toFloat(&ok), 0.0f); - QVERIFY(!ok); - - const QByteArray data("0.000000000931322574615478515625"); - const float expectedValue = 9.31322574615478515625e-10f; - QCOMPARE(data.toFloat(&ok), expectedValue); - QVERIFY(ok); -} - -void tst_QByteArray::toDouble_data() -{ - QTest::addColumn<QByteArray>("string"); - QTest::addColumn<double>("expectedNumber"); - QTest::addColumn<bool>("expectedOk"); - - QTest::newRow("null") << QByteArray() << 0.0 << false; - QTest::newRow("empty") << QByteArray("") << 0.0 << false; - - QTest::newRow("decimal") << QByteArray("1.2345") << 1.2345 << true; - QTest::newRow("exponent lowercase") << QByteArray("1.2345e+01") << 12.345 << true; - QTest::newRow("exponent uppercase") << QByteArray("1.2345E+02") << 123.45 << true; - QTest::newRow("leading spaces") << QByteArray(" \n\r\t1.2345") << 1.2345 << true; - QTest::newRow("trailing spaces") << QByteArray("1.2345 \n\r\t") << 1.2345 << true; - QTest::newRow("leading junk") << QByteArray("x1.2345") << 0.0 << false; - QTest::newRow("trailing junk") << QByteArray("1.2345x") << 0.0 << false; - QTest::newRow("high precision") << QByteArray("0.000000000931322574615478515625") - << 0.000000000931322574615478515625 << true; - - QTest::newRow("raw, null plus junk") << QByteArray::fromRawData("1.2\0 junk", 9) << 0.0 << false; - QTest::newRow("raw, null-terminator not included") << QByteArray::fromRawData("2.3", 3) << 2.3 << true; -} - -void tst_QByteArray::toDouble() -{ - QFETCH(QByteArray, string); - QFETCH(double, expectedNumber); - QFETCH(bool, expectedOk); - - bool ok; - const double number = string.toDouble(&ok); - - QCOMPARE(ok, expectedOk); - QCOMPARE(number, expectedNumber); -} - -void tst_QByteArray::toLong_data() -{ - QTest::addColumn<QByteArray>("str"); - QTest::addColumn<int>("base"); - QTest::addColumn<long>("result"); - QTest::addColumn<bool>("ok"); - - QTest::newRow("null") << QByteArray() << 10 << 0L << false; - QTest::newRow("empty") << QByteArray("") << 16 << 0L << false; - QTest::newRow("in range dec") << QByteArray("1608507359") << 10 << 1608507359L << true; - QTest::newRow("in range dec neg") << QByteArray("-1608507359") << 10 << -1608507359L << true; - QTest::newRow("in range hex") << QByteArray("12ABCDEF") << 16 << 0x12ABCDEFL << true; - QTest::newRow("in range hex neg") << QByteArray("-12ABCDEF") << 16 << -0x12ABCDEFL << true; - QTest::newRow("Fibonacci's last int32") << QByteArray("1836311903") << 10 << 1836311903L - << true; - - QTest::newRow("leading spaces") << QByteArray(" \r\n\tABC123") << 16 << 0xABC123L << true; - QTest::newRow("trailing spaces") << QByteArray("1234567\t\r \n") << 10 << 1234567L << true; - QTest::newRow("leading junk") << QByteArray("q12345") << 10 << 0L << false; - QTest::newRow("trailing junk") << QByteArray("abc12345t") << 16 << 0L << false; - - QTest::newRow("dec with base 0") << QByteArray("123") << 0 << 123L << true; - QTest::newRow("neg dec with base 0") << QByteArray("-123") << 0 << -123L << true; - QTest::newRow("hex with base 0") << QByteArray("0x123") << 0 << 0x123L << true; - QTest::newRow("neg hex with base 0") << QByteArray("-0x123") << 0 << -0x123L << true; - QTest::newRow("oct with base 0") << QByteArray("0123") << 0 << 0123L << true; - QTest::newRow("neg oct with base 0") << QByteArray("-0123") << 0 << -0123L << true; - - QTest::newRow("base 3") << QByteArray("12012") << 3 << 140L << true; - QTest::newRow("neg base 3") << QByteArray("-201") << 3 << -19L << true; - - using Bounds = std::numeric_limits<long>; - QTest::newRow("long max") << QByteArray::number(Bounds::max()) << 10 << Bounds::max() << true; - QTest::newRow("long min") << QByteArray::number(Bounds::min()) << 10 << Bounds::min() << true; - - using B32 = std::numeric_limits<qint32>; - QTest::newRow("int32 min bin") << (QByteArray("-1") + QByteArray(31, '0')) << 2 - << long(B32::min()) << true; - QTest::newRow("int32 max bin") << QByteArray(31, '1') << 2 << long(B32::max()) << true; - QTest::newRow("int32 min hex") << QByteArray("-80000000") << 16 << long(B32::min()) << true; - QTest::newRow("int32 max hex") << QByteArray("7fffffff") << 16 << long(B32::max()) << true; - QTest::newRow("int32 min dec") << QByteArray("-2147483648") << 10 << long(B32::min()) << true; - QTest::newRow("int32 max dec") << QByteArray("2147483647") << 10 << long(B32::max()) << true; - - if constexpr (sizeof(long) < sizeof(qlonglong)) { - const qlonglong longMaxPlusOne = static_cast<qlonglong>(Bounds::max()) + 1; - const qlonglong longMinMinusOne = static_cast<qlonglong>(Bounds::min()) - 1; - QTest::newRow("long max + 1") << QByteArray::number(longMaxPlusOne) << 10 << 0L << false; - QTest::newRow("long min - 1") << QByteArray::number(longMinMinusOne) << 10 << 0L << false; + QFETCH( QByteArray, expected ); + QCOMPARE(QByteArray::number(n, base), expected); + QCOMPARE(QByteArray::number(-n, base), '-' + expected); + + // check qlonglong->QByteArray->qlonglong round trip + for (int ibase = 2; ibase <= 36; ++ibase) { + auto stringrep = QByteArray::number(n, ibase); + QCOMPARE(QByteArray::number(-n, ibase), '-' + stringrep); + bool ok(false); + auto result = stringrep.toLongLong(&ok, ibase); + QVERIFY(ok); + QCOMPARE(n, result); } -} - -void tst_QByteArray::toLong() -{ - QFETCH(QByteArray, str); - QFETCH(int, base); - QFETCH(long, result); - QFETCH(bool, ok); - - bool b; - QCOMPARE(str.toLong(nullptr, base), result); - QCOMPARE(str.toLong(&b, base), result); - QCOMPARE(b, ok); - if (base == 10) { - // check that by default base is assumed to be 10 - QCOMPARE(str.toLong(&b), result); - QCOMPARE(b, ok); + if (n <= std::numeric_limits<int>::max()) { + QCOMPARE(QByteArray::number(int(n), base), expected); + QCOMPARE(QByteArray::number(int(-n), base), '-' + expected); + } else if (n <= std::numeric_limits<long>::max()) { + QCOMPARE(QByteArray::number(long(n), base), expected); + QCOMPARE(QByteArray::number(long(-n), base), '-' + expected); } } -void tst_QByteArray::toULong_data() +void tst_QByteArray::nullness() { - QTest::addColumn<QByteArray>("str"); - QTest::addColumn<int>("base"); - QTest::addColumn<ulong>("result"); - QTest::addColumn<bool>("ok"); - - ulong LongMaxPlusOne = (ulong)LONG_MAX + 1; - QTest::newRow("LONG_MAX+1") << QString::number(LongMaxPlusOne).toUtf8() << 10 << LongMaxPlusOne << true; - QTest::newRow("null") << QByteArray() << 10 << 0UL << false; - QTest::newRow("empty") << QByteArray("") << 10 << 0UL << false; - QTest::newRow("ulong1") << QByteArray("3234567890") << 10 << 3234567890UL << true; - QTest::newRow("ulong2") << QByteArray("fFFfFfFf") << 16 << 0xFFFFFFFFUL << true; - - QTest::newRow("leading spaces") << QByteArray(" \n\r\t100") << 10 << 100UL << true; - QTest::newRow("trailing spaces") << QByteArray("100 \n\r\t") << 10 << 100UL << true; - QTest::newRow("leading junk") << QByteArray("x100") << 10 << 0UL << false; - QTest::newRow("trailing junk") << QByteArray("100x") << 10 << 0UL << false; -} - -void tst_QByteArray::toULong() -{ - QFETCH(QByteArray, str); - QFETCH(int, base); - QFETCH(ulong, result); - QFETCH(bool, ok); - - bool b; - QCOMPARE(str.toULong(0, base), result); - QCOMPARE(str.toULong(&b, base), result); - QCOMPARE(b, ok); -} - -void tst_QByteArray::toLongLong_data() -{ - QTest::addColumn<QByteArray>("str"); - QTest::addColumn<int>("base"); - QTest::addColumn<qlonglong>("result"); - QTest::addColumn<bool>("ok"); - - QTest::newRow("null") << QByteArray() << 10 << 0LL << false; - QTest::newRow("empty") << QByteArray("") << 10 << 0LL << false; - QTest::newRow("out of base bound") << QByteArray("c") << 10 << 0LL << false; - - QTest::newRow("in range dec") << QByteArray("7679359922672374856") << 10 - << 7679359922672374856LL << true; - QTest::newRow("in range dec neg") << QByteArray("-7679359922672374856") << 10 - << -7679359922672374856LL << true; - QTest::newRow("in range hex") << QByteArray("6A929129A5421448") << 16 << 0x6A929129A5421448LL - << true; - QTest::newRow("in range hex neg") << QByteArray("-6A929129A5421448") << 16 - << -0x6A929129A5421448LL << true; - QTest::newRow("Fibonacci's last int64") << QByteArray("7540113804746346429") << 10 - << 7540113804746346429LL << true; - - QTest::newRow("leading spaces") << QByteArray(" \r\n\tABCFFFFFFF123") << 16 - << 0xABCFFFFFFF123LL << true; - QTest::newRow("trailing spaces") << QByteArray("9876543210\t\r \n") << 10 - << 9876543210LL << true; - QTest::newRow("leading junk") << QByteArray("q12345") << 10 << 0LL << false; - QTest::newRow("trailing junk") << QByteArray("abc12345t") << 16 << 0LL << false; - - QTest::newRow("dec with base 0") << QByteArray("9876543210") << 0 << 9876543210LL << true; - QTest::newRow("neg dec with base 0") << QByteArray("-9876543210") << 0 << -9876543210LL << true; - QTest::newRow("hex with base 0") << QByteArray("0x9876543210") << 0 << 0x9876543210LL << true; - QTest::newRow("neg hex with base 0") << QByteArray("-0x9876543210") << 0 << -0x9876543210LL - << true; - QTest::newRow("oct with base 0") << QByteArray("07654321234567") << 0 << 07654321234567LL - << true; - QTest::newRow("neg oct with base 0") << QByteArray("-07654321234567") << 0 << -07654321234567LL - << true; - - QTest::newRow("base 3") << QByteArray("12012") << 3 << 140LL << true; - QTest::newRow("neg base 3") << QByteArray("-201") << 3 << -19LL << true; - - QTest::newRow("max dec") << QByteArray("9223372036854775807") << 10 << 9223372036854775807LL - << true; - QTest::newRow("mix hex") << QByteArray("-7FFFFFFFFFFFFFFF") << 16 << -0x7FFFFFFFFFFFFFFFLL - << true; - - QTest::newRow("max + 1 dec") << QByteArray("9223372036854775808") << 10 << 0LL << false; - QTest::newRow("min - 1 hex") << QByteArray("-8000000000000001") << 16 << 0LL << false; -} - -void tst_QByteArray::toLongLong() -{ - QFETCH(QByteArray, str); - QFETCH(int, base); - QFETCH(qlonglong, result); - QFETCH(bool, ok); - - bool b; - QCOMPARE(str.toLongLong(nullptr, base), result); - QCOMPARE(str.toLongLong(&b, base), result); - QCOMPARE(b, ok); - if (base == 10) { - QCOMPARE(str.toLongLong(&b), result); - QCOMPARE(b, ok); + { + QByteArray ba; + QVERIFY(ba.isNull()); + } + { + QByteArray ba = nullptr; + QVERIFY(ba.isNull()); + } + { + const char *ptr = nullptr; + QByteArray ba = ptr; + QVERIFY(ba.isNull()); + } + { + QByteArray ba(nullptr, 0); + QVERIFY(ba.isNull()); + } + { + const char *ptr = nullptr; + QByteArray ba(ptr, 0); + QVERIFY(ba.isNull()); + } + { + QByteArrayView bav; + QVERIFY(bav.isNull()); + QByteArray ba = bav.toByteArray(); + QVERIFY(ba.isNull()); } -} - -void tst_QByteArray::toULongLong_data() -{ - QTest::addColumn<QByteArray>("str"); - QTest::addColumn<int>("base"); - QTest::addColumn<qulonglong>("result"); - QTest::addColumn<bool>("ok"); - - QTest::newRow("null") << QByteArray() << 10 << (qulonglong)0 << false; - QTest::newRow("empty") << QByteArray("") << 10 << (qulonglong)0 << false; - QTest::newRow("out of base bound") << QByteArray("c") << 10 << (qulonglong)0 << false; - - QTest::newRow("leading spaces") << QByteArray(" \n\r\t100") << 10 << qulonglong(100) << true; - QTest::newRow("trailing spaces") << QByteArray("100 \n\r\t") << 10 << qulonglong(100) << true; - QTest::newRow("leading junk") << QByteArray("x100") << 10 << qulonglong(0) << false; - QTest::newRow("trailing junk") << QByteArray("100x") << 10 << qulonglong(0) << false; -} - -void tst_QByteArray::toULongLong() -{ - QFETCH(QByteArray, str); - QFETCH(int, base); - QFETCH(qulonglong, result); - QFETCH(bool, ok); - - bool b; - QCOMPARE(str.toULongLong(0, base), result); - QCOMPARE(str.toULongLong(&b, base), result); - QCOMPARE(b, ok); } static bool checkSize(qsizetype value, qsizetype min) @@ -1716,7 +1638,7 @@ void tst_QByteArray::blockSizeCalculations() QCOMPARE(qCalculateGrowingBlockSize(MaxAllocSize/2, 2, 1).elementCount, qsizetype(MaxAllocSize)/2); // error conditions - QCOMPARE(qCalculateBlockSize(qint64(MaxAllocSize) + 1, 1), qsizetype(-1)); + QCOMPARE(qCalculateBlockSize(quint64(MaxAllocSize) + 1, 1), qsizetype(-1)); QCOMPARE(qCalculateBlockSize(qsizetype(-1), 1), qsizetype(-1)); QCOMPARE(qCalculateBlockSize(MaxAllocSize, 1, 1), qsizetype(-1)); QCOMPARE(qCalculateBlockSize(MaxAllocSize/2 + 1, 2), qsizetype(-1)); @@ -1773,7 +1695,8 @@ void tst_QByteArray::blockSizeCalculations() QVERIFY(checkSize(alloc, qsizetype(MaxAllocSize) / elementSize)); // the next allocation should be invalid - QCOMPARE(qCalculateGrowingBlockSize(alloc + 1, elementSize).size, qsizetype(-1)); + if (alloc < MaxAllocSize) // lest alloc + 1 overflows (= UB) + QCOMPARE(qCalculateGrowingBlockSize(alloc + 1, elementSize).size, qsizetype(-1)); } } @@ -1789,17 +1712,6 @@ void tst_QByteArray::resizeAfterFromRawData() QVERIFY(array.constData()[5] == 0); } -void tst_QByteArray::appendAfterFromRawData() -{ - QByteArray arr; - { - char data[] = "X"; - arr += QByteArray::fromRawData(data, sizeof(data)); - data[0] = 'Y'; - } - QCOMPARE(arr.at(0), 'X'); -} - void tst_QByteArray::toFromHex_data() { QTest::addColumn<QByteArray>("str"); @@ -1879,7 +1791,7 @@ void tst_QByteArray::toFromHex_data() << QByteArray("af") << QByteArray("xaf"); - QTest::newRow("no-leading-zero") + QTest::newRow("no-leading-zero-long") << QByteArray("\xd\xde\xad\xc0\xde") << '\0' << QByteArray("0ddeadc0de") @@ -1940,16 +1852,16 @@ void tst_QByteArray::toFromPercentEncoding() QCOMPARE(QByteArray("").toPercentEncoding(), QByteArray("")); QByteArray data = arr.toPercentEncoding(); - QCOMPARE(QString(data), QString("Qt%20is%20great%21")); - QCOMPARE(QByteArray::fromPercentEncoding(data), arr); + QCOMPARE(data, QByteArray("Qt%20is%20great%21")); + QCOMPARE(data.percentDecoded(), arr); data = arr.toPercentEncoding("! ", "Qt"); - QCOMPARE(QString(data), QString("%51%74 is grea%74!")); - QCOMPARE(QByteArray::fromPercentEncoding(data), arr); + QCOMPARE(data, QByteArray("%51%74 is grea%74!")); + QCOMPARE(data.percentDecoded(), arr); data = arr.toPercentEncoding(QByteArray(), "abcdefghijklmnopqrstuvwxyz", 'Q'); - QCOMPARE(QString(data), QString("Q51Q74Q20Q69Q73Q20Q67Q72Q65Q61Q74Q21")); - QCOMPARE(QByteArray::fromPercentEncoding(data, 'Q'), arr); + QCOMPARE(data, QByteArray("Q51Q74Q20Q69Q73Q20Q67Q72Q65Q61Q74Q21")); + QCOMPARE(data.percentDecoded('Q'), arr); // verify that to/from percent encoding preserves nullity arr = ""; @@ -1965,8 +1877,16 @@ void tst_QByteArray::toFromPercentEncoding() QVERIFY(arr.isNull()); QVERIFY(arr.toPercentEncoding().isEmpty()); QVERIFY(arr.toPercentEncoding().isNull()); - QVERIFY(QByteArray::fromPercentEncoding(QByteArray()).isEmpty()); - QVERIFY(QByteArray::fromPercentEncoding(QByteArray()).isNull()); + QVERIFY(QByteArray().percentDecoded().isEmpty()); + QVERIFY(QByteArray().percentDecoded().isNull()); + + // Verify that literal % in the string to be encoded does round-trip: + arr = "Qt%20is%20great%21"; + data = arr.toPercentEncoding(); + QCOMPARE(data.percentDecoded(), arr); + arr = "87% of all statistics are made up!"; + data = arr.toPercentEncoding(); + QCOMPARE(data.percentDecoded(), arr); } void tst_QByteArray::fromPercentEncoding_data() @@ -1988,7 +1908,7 @@ void tst_QByteArray::fromPercentEncoding() QFETCH(QByteArray, encodedString); QFETCH(QByteArray, decodedString); - QCOMPARE(QByteArray::fromPercentEncoding(encodedString), decodedString); + QCOMPARE(encodedString.percentDecoded(), decodedString); } void tst_QByteArray::toPercentEncoding_data() @@ -2013,36 +1933,34 @@ void tst_QByteArray::toPercentEncoding() QCOMPARE(decodedString.toPercentEncoding("/.").constData(), encodedString.constData()); } -void tst_QByteArray::toPercentEncoding2_data() +void tst_QByteArray::pecentEncodingRoundTrip_data() { QTest::addColumn<QByteArray>("original"); QTest::addColumn<QByteArray>("encoded"); QTest::addColumn<QByteArray>("excludeInEncoding"); QTest::addColumn<QByteArray>("includeInEncoding"); - QTest::newRow("test_01") << QByteArray("abcdevghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ012345678-._~") - << QByteArray("abcdevghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ012345678-._~") - << QByteArray("") - << QByteArray(""); - QTest::newRow("test_02") << QByteArray("{\t\n\r^\"abc}") - << QByteArray("%7B%09%0A%0D%5E%22abc%7D") - << QByteArray("") - << QByteArray(""); - QTest::newRow("test_03") << QByteArray("://?#[]@!$&'()*+,;=") - << QByteArray("%3A%2F%2F%3F%23%5B%5D%40%21%24%26%27%28%29%2A%2B%2C%3B%3D") - << QByteArray("") - << QByteArray(""); - QTest::newRow("test_04") << QByteArray("://?#[]@!$&'()*+,;=") - << QByteArray("%3A%2F%2F%3F%23%5B%5D%40!$&'()*+,;=") - << QByteArray("!$&'()*+,;=") - << QByteArray(""); - QTest::newRow("test_05") << QByteArray("abcd") - << QByteArray("a%62%63d") - << QByteArray("") - << QByteArray("bc"); -} - -void tst_QByteArray::toPercentEncoding2() + QTest::newRow("unchanged") + << QByteArray("abcdevghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ012345678-._~") + << QByteArray("abcdevghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ012345678-._~") + << QByteArray("") << QByteArray(""); + QTest::newRow("enclosed-space-quote") + << QByteArray("{\t\n\r^\"abc}") + << QByteArray("%7B%09%0A%0D%5E%22abc%7D") + << QByteArray("") << QByteArray(""); + QTest::newRow("punctuate") + << QByteArray("://?#[]@!$&'()*+,;=") + << QByteArray("%3A%2F%2F%3F%23%5B%5D%40%21%24%26%27%28%29%2A%2B%2C%3B%3D") + << QByteArray("") << QByteArray(""); + QTest::newRow("punctuate-exclude") + << QByteArray("://?#[]@!$&'()*+,;=") + << QByteArray("%3A%2F%2F%3F%23%5B%5D%40!$&'()*+,;=") + << QByteArray("!$&'()*+,;=") << QByteArray(""); + QTest::newRow("text-include") + << QByteArray("abcd") << QByteArray("a%62%63d") << QByteArray("") << QByteArray("bc"); +} + +void tst_QByteArray::pecentEncodingRoundTrip() { QFETCH(QByteArray, original); QFETCH(QByteArray, encoded); @@ -2050,8 +1968,8 @@ void tst_QByteArray::toPercentEncoding2() QFETCH(QByteArray, includeInEncoding); QByteArray encodedData = original.toPercentEncoding(excludeInEncoding, includeInEncoding); - QCOMPARE(encodedData.constData(), encoded.constData()); - QCOMPARE(original, QByteArray::fromPercentEncoding(encodedData)); + QCOMPARE(encodedData, encoded); + QCOMPARE(encodedData.percentDecoded(), original); } struct StringComparisonData @@ -2134,52 +2052,49 @@ void tst_QByteArray::compare_singular() void tst_QByteArray::compareCharStar_data() { QTest::addColumn<QByteArray>("str1"); - QTest::addColumn<QString>("string2"); + QTest::addColumn<QByteArray>("string2"); QTest::addColumn<int>("result"); - QTest::newRow("null-null") << QByteArray() << QString() << 0; - QTest::newRow("null-empty") << QByteArray() << "" << 0; - QTest::newRow("null-full") << QByteArray() << "abc" << -1; - QTest::newRow("empty-null") << QByteArray("") << QString() << 0; - QTest::newRow("empty-empty") << QByteArray("") << "" << 0; - QTest::newRow("empty-full") << QByteArray("") << "abc" << -1; - QTest::newRow("raw-null") << QByteArray::fromRawData("abc", 0) << QString() << 0; - QTest::newRow("raw-empty") << QByteArray::fromRawData("abc", 0) << QString("") << 0; - QTest::newRow("raw-full") << QByteArray::fromRawData("abc", 0) << "abc" << -1; + QTest::newRow("null-null") << QByteArray() << QByteArray() << 0; + QTest::newRow("null-empty") << QByteArray() << QByteArray("") << 0; + QTest::newRow("null-full") << QByteArray() << QByteArray("abc") << -1; + QTest::newRow("empty-null") << QByteArray("") << QByteArray() << 0; + QTest::newRow("empty-empty") << QByteArray("") << QByteArray("") << 0; + QTest::newRow("empty-full") << QByteArray("") << QByteArray("abc") << -1; + QTest::newRow("raw-null") << QByteArray::fromRawData("abc", 0) << QByteArray() << 0; + QTest::newRow("raw-empty") << QByteArray::fromRawData("abc", 0) << QByteArray("") << 0; + QTest::newRow("raw-full") << QByteArray::fromRawData("abc", 0) << QByteArray("abc") << -1; - QTest::newRow("full-null") << QByteArray("abc") << QString() << +1; - QTest::newRow("full-empty") << QByteArray("abc") << "" << +1; + QTest::newRow("full-null") << QByteArray("abc") << QByteArray() << +1; + QTest::newRow("full-empty") << QByteArray("abc") << QByteArray("") << +1; - QTest::newRow("equal1") << QByteArray("abc") << "abc" << 0; - QTest::newRow("equal2") << QByteArray("abcd", 3) << "abc" << 0; - QTest::newRow("equal3") << QByteArray::fromRawData("abcd", 3) << "abc" << 0; + QTest::newRow("equal1") << QByteArray("abc") << QByteArray("abc") << 0; + QTest::newRow("equal2") << QByteArray("abcd", 3) << QByteArray("abc") << 0; + QTest::newRow("equal3") << QByteArray::fromRawData("abcd", 3) << QByteArray("abc") << 0; - QTest::newRow("less1") << QByteArray("ab") << "abc" << -1; - QTest::newRow("less2") << QByteArray("abb") << "abc" << -1; - QTest::newRow("less3") << QByteArray::fromRawData("abc", 2) << "abc" << -1; - QTest::newRow("less4") << QByteArray("", 1) << "abc" << -1; - QTest::newRow("less5") << QByteArray::fromRawData("", 1) << "abc" << -1; - QTest::newRow("less6") << QByteArray("a\0bc", 4) << "a.bc" << -1; + QTest::newRow("less1") << QByteArray("ab") << QByteArray("abc") << -1; + QTest::newRow("less2") << QByteArray("abb") << QByteArray("abc") << -1; + QTest::newRow("less3") << QByteArray::fromRawData("abc", 2) << QByteArray("abc") << -1; + QTest::newRow("less4") << QByteArray("", 1) << QByteArray("abc") << -1; + QTest::newRow("less5") << QByteArray::fromRawData("", 1) << QByteArray("abc") << -1; + QTest::newRow("less6") << QByteArray("a\0bc", 4) << QByteArray("a.bc") << -1; - QTest::newRow("greater1") << QByteArray("ac") << "abc" << +1; - QTest::newRow("greater2") << QByteArray("abd") << "abc" << +1; - QTest::newRow("greater3") << QByteArray("abcd") << "abc" << +1; - QTest::newRow("greater4") << QByteArray::fromRawData("abcd", 4) << "abc" << +1; + QTest::newRow("greater1") << QByteArray("ac") << QByteArray("abc") << +1; + QTest::newRow("greater2") << QByteArray("abd") << QByteArray("abc") << +1; + QTest::newRow("greater3") << QByteArray("abcd") << QByteArray("abc") << +1; + QTest::newRow("greater4") << QByteArray::fromRawData("abcd", 4) << QByteArray("abc") << +1; } void tst_QByteArray::compareCharStar() { QFETCH(QByteArray, str1); - QFETCH(QString, string2); + QFETCH(QByteArray, string2); QFETCH(int, result); const bool isEqual = result == 0; const bool isLess = result < 0; const bool isGreater = result > 0; - QByteArray qba = string2.toUtf8(); - const char *str2 = qba.constData(); - if (string2.isNull()) - str2 = 0; + const char *str2 = string2.isNull() ? nullptr : string2.constData(); // basic tests: QCOMPARE(str1 == str2, isEqual); @@ -2377,9 +2292,26 @@ void tst_QByteArray::reserveExtended() QCOMPARE(array.capacity(), array.size()); } -void tst_QByteArray::movablity_data() +void tst_QByteArray::resize() { - QTest::addColumn<QByteArray>("array"); + QByteArray ba; + ba.resize(15); + QCOMPARE(ba.size(), qsizetype(15)); + ba.resize(10); + QCOMPARE(ba.size(), 10); + ba.resize(0); + QCOMPARE(ba.size(), 0); + ba.resize(5, 'a'); + QCOMPARE(ba.size(), 5); + QCOMPARE(ba, "aaaaa"); + ba.resize(10, 'b'); + QCOMPARE(ba.size(), 10); + QCOMPARE(ba, "aaaaabbbbb"); +} + +void tst_QByteArray::movability_data() +{ + prependExtended_data(); QTest::newRow("0x00000000") << QByteArray("\x00\x00\x00\x00", 4); QTest::newRow("0x000000ff") << QByteArray("\x00\x00\x00\xff", 4); @@ -2387,11 +2319,9 @@ void tst_QByteArray::movablity_data() QTest::newRow("empty") << QByteArray(""); QTest::newRow("null") << QByteArray(); QTest::newRow("sss") << QByteArray(3, 's'); - - prependExtended_data(); } -void tst_QByteArray::movablity() +void tst_QByteArray::movability() { QFETCH(QByteArray, array); @@ -2462,7 +2392,7 @@ void tst_QByteArray::literals() { QByteArray str(QByteArrayLiteral("abcd")); - QVERIFY(str.length() == 4); + QVERIFY(str.size() == 4); QCOMPARE(str.capacity(), 0); QVERIFY(str == "abcd"); QVERIFY(!str.data_ptr()->isMutable()); @@ -2474,34 +2404,60 @@ void tst_QByteArray::literals() // detach on non const access QVERIFY(str.data() != s); - QVERIFY(str.capacity() >= str.length()); + QVERIFY(str.capacity() >= str.size()); QVERIFY(str2.constData() == s); QVERIFY(str2.data() != s); - QVERIFY(str2.capacity() >= str2.length()); + QVERIFY(str2.capacity() >= str2.size()); } void tst_QByteArray::userDefinedLiterals() { - QByteArray str = "abcd"_qba; + { + QByteArray str = "abcd"_ba; - QVERIFY(str.length() == 4); - QCOMPARE(str.capacity(), 0); - QVERIFY(str == "abcd"); - QVERIFY(!str.data_ptr()->isMutable()); + QVERIFY(str.size() == 4); + QCOMPARE(str.capacity(), 0); + QVERIFY(str == "abcd"); + QVERIFY(!str.data_ptr()->isMutable()); - const char *s = str.constData(); - QByteArray str2 = str; - QVERIFY(str2.constData() == s); - QCOMPARE(str2.capacity(), 0); + const char *s = str.constData(); + QByteArray str2 = str; + QVERIFY(str2.constData() == s); + QCOMPARE(str2.capacity(), 0); - // detach on non const access - QVERIFY(str.data() != s); - QVERIFY(str.capacity() >= str.length()); + // detach on non const access + QVERIFY(str.data() != s); + QVERIFY(str.capacity() >= str.size()); - QVERIFY(str2.constData() == s); - QVERIFY(str2.data() != s); - QVERIFY(str2.capacity() >= str2.length()); + QVERIFY(str2.constData() == s); + QVERIFY(str2.data() != s); + QVERIFY(str2.capacity() >= str2.size()); + } + +#if QT_DEPRECATED_SINCE(6, 8) + { + QT_IGNORE_DEPRECATIONS(QByteArray str = "abcd"_qba;) + + QVERIFY(str.size() == 4); + QCOMPARE(str.capacity(), 0); + QVERIFY(str == "abcd"); + QVERIFY(!str.data_ptr()->isMutable()); + + const char *s = str.constData(); + QByteArray str2 = str; + QVERIFY(str2.constData() == s); + QCOMPARE(str2.capacity(), 0); + + // detach on non const access + QVERIFY(str.data() != s); + QVERIFY(str.capacity() >= str.size()); + + QVERIFY(str2.constData() == s); + QVERIFY(str2.data() != s); + QVERIFY(str2.capacity() >= str2.size()); + } +#endif // QT_DEPRECATED_SINCE(6, 8) } void tst_QByteArray::toUpperLower_data() @@ -2534,10 +2490,16 @@ void tst_QByteArray::toUpperLower() QFETCH(QByteArray, input); QFETCH(QByteArray, upper); QFETCH(QByteArray, lower); + QVERIFY(upper.isUpper()); + QVERIFY(lower.isLower()); QCOMPARE(lower.toLower(), lower); + QVERIFY(lower.toLower().isLower()); QCOMPARE(upper.toUpper(), upper); + QVERIFY(upper.toUpper().isUpper()); QCOMPARE(input.toUpper(), upper); + QVERIFY(input.toUpper().isUpper()); QCOMPARE(input.toLower(), lower); + QVERIFY(input.toLower().isLower()); QByteArray copy = input; QCOMPARE(std::move(copy).toUpper(), upper); @@ -2566,12 +2528,12 @@ void tst_QByteArray::toUpperLower() void tst_QByteArray::isUpper() { - QVERIFY(!QByteArray().isUpper()); - QVERIFY(!QByteArray("").isUpper()); + QVERIFY(QByteArray().isUpper()); + QVERIFY(QByteArray("").isUpper()); QVERIFY(QByteArray("TEXT").isUpper()); - QVERIFY(!QByteArray("\xD0\xDE").isUpper()); // non-ASCII is neither upper nor lower - QVERIFY(!QByteArray("\xD7").isUpper()); - QVERIFY(!QByteArray("\xDF").isUpper()); + QVERIFY(QByteArray("\xD0\xDE").isUpper()); + QVERIFY(QByteArray("\xD7").isUpper()); + QVERIFY(QByteArray("\xDF").isUpper()); QVERIFY(!QByteArray("text").isUpper()); QVERIFY(!QByteArray("Text").isUpper()); QVERIFY(!QByteArray("tExt").isUpper()); @@ -2581,19 +2543,19 @@ void tst_QByteArray::isUpper() QVERIFY(!QByteArray("teXT").isUpper()); QVERIFY(!QByteArray("tEXt").isUpper()); QVERIFY(!QByteArray("tExT").isUpper()); - QVERIFY(!QByteArray("@ABYZ[").isUpper()); + QVERIFY(QByteArray("@ABYZ[").isUpper()); QVERIFY(!QByteArray("@abyz[").isUpper()); - QVERIFY(!QByteArray("`ABYZ{").isUpper()); + QVERIFY(QByteArray("`ABYZ{").isUpper()); QVERIFY(!QByteArray("`abyz{").isUpper()); } void tst_QByteArray::isLower() { - QVERIFY(!QByteArray().isLower()); - QVERIFY(!QByteArray("").isLower()); + QVERIFY(QByteArray().isLower()); + QVERIFY(QByteArray("").isLower()); QVERIFY(QByteArray("text").isLower()); - QVERIFY(!QByteArray("\xE0\xFF").isLower()); // non-ASCII is neither upper nor lower - QVERIFY(!QByteArray("\xF7").isLower()); + QVERIFY(QByteArray("\xE0\xFF").isLower()); + QVERIFY(QByteArray("\xF7").isLower()); QVERIFY(!QByteArray("Text").isLower()); QVERIFY(!QByteArray("tExt").isLower()); QVERIFY(!QByteArray("teXt").isLower()); @@ -2604,14 +2566,14 @@ void tst_QByteArray::isLower() QVERIFY(!QByteArray("tExT").isLower()); QVERIFY(!QByteArray("TEXT").isLower()); QVERIFY(!QByteArray("@ABYZ[").isLower()); - QVERIFY(!QByteArray("@abyz[").isLower()); + QVERIFY(QByteArray("@abyz[").isLower()); QVERIFY(!QByteArray("`ABYZ{").isLower()); - QVERIFY(!QByteArray("`abyz{").isLower()); + QVERIFY(QByteArray("`abyz{").isLower()); } void tst_QByteArray::macTypes() { -#ifndef Q_OS_MAC +#ifndef Q_OS_DARWIN QSKIP("This is a Apple-only test"); #else extern void tst_QByteArray_macTypes(); // in qbytearray_mac.mm @@ -2624,7 +2586,7 @@ void tst_QByteArray::stdString() std::string stdstr( "QByteArray" ); const QByteArray stlqt = QByteArray::fromStdString(stdstr); - QCOMPARE(stlqt.length(), int(stdstr.length())); + QCOMPARE(stlqt.size(), int(stdstr.length())); QCOMPARE(stlqt.data(), stdstr.c_str()); QCOMPARE(stlqt.toStdString(), stdstr); @@ -2719,30 +2681,37 @@ void tst_QByteArray::truncate() QVERIFY(a.isEmpty()); } -void tst_QByteArray::trimmed() +void tst_QByteArray::trimmed_data() { - QFETCH(QByteArray, source); - QFETCH(QByteArray, expected); + QTest::addColumn<QByteArray>("full" ); + QTest::addColumn<QByteArray>("trimmed" ); - QCOMPARE(source.trimmed(), expected); - QByteArray copy = source; - QCOMPARE(std::move(copy).trimmed(), expected); - - if (source.isEmpty()) - QVERIFY(!source.isDetached()); + QTest::addRow("null") << QByteArray() << QByteArray(); + QTest::addRow("simple") << "Text"_ba << "Text"_ba; + QTest::addRow("single-space") << " "_ba << ""_ba; + QTest::addRow("single-char") << " a "_ba << "a"_ba; + QTest::addRow("mixed") << " a \n\t\v b "_ba << "a \n\t\v b"_ba; } -void tst_QByteArray::trimmed_data() +void tst_QByteArray::trimmed() { - QTest::addColumn<QByteArray>("source"); - QTest::addColumn<QByteArray>("expected"); + QFETCH(QByteArray, full); + QFETCH(QByteArray, trimmed); - QTest::newRow("null") << QByteArray() << QByteArray(); - QTest::newRow("empty") << QByteArray("") << QByteArray(""); - QTest::newRow("no spaces") << QByteArray("a b\nc\td") << QByteArray("a b\nc\td"); - QTest::newRow("with spaces") << QByteArray("\t \v a b\r\nc \td\ve f \r\n\f") - << QByteArray("a b\r\nc \td\ve f"); - QTest::newRow("all spaces") << QByteArray("\t \r \n \v \f") << QByteArray(""); + // Shared + if (!full.isNull()) + QVERIFY(!full.isDetached()); + QCOMPARE(full.trimmed(), trimmed); // lvalue + QCOMPARE(QByteArray(full).trimmed(), trimmed); // rvalue + QCOMPARE(full.isNull(), trimmed.isNull()); + + // Not shared + full = QByteArrayView(full).toByteArray(); + if (!full.isNull()) + QVERIFY(full.isDetached()); + QCOMPARE(full.trimmed(), trimmed); // lvalue + QCOMPARE(QByteArray(full).trimmed(), trimmed); // rvalue + QCOMPARE(full.isNull(), trimmed.isNull()); } void tst_QByteArray::simplified() @@ -2774,45 +2743,99 @@ void tst_QByteArray::simplified_data() void tst_QByteArray::left() { QByteArray a; + QCOMPARE(QByteArray().left(0), QByteArray()); + QCOMPARE(QByteArray().left(10), QByteArray()); QCOMPARE(a.left(0), QByteArray()); QCOMPARE(a.left(10), QByteArray()); QVERIFY(!a.isDetached()); + QCOMPARE(QByteArray(a).left(0), QByteArray()); + QCOMPARE(QByteArray(a).left(10), QByteArray()); + QCOMPARE(detached(a).left(0), QByteArray()); + QCOMPARE(detached(a).left(10), QByteArray()); a = QByteArray("abcdefgh"); const char *ptr = a.constData(); + + // lvalue QCOMPARE(a.left(5), QByteArray("abcde")); QCOMPARE(a.left(20), a); QCOMPARE(a.left(-5), QByteArray()); // calling left() does not modify the source array QCOMPARE(a.constData(), ptr); + + // rvalue, not detached + QCOMPARE(QByteArray(a).left(5), QByteArray("abcde")); + QCOMPARE(QByteArray(a).left(20), a); + QCOMPARE(QByteArray(a).left(-5), QByteArray()); + // calling left() does not modify the source array + QCOMPARE(a.constData(), ptr); + + // rvalue, detached + QCOMPARE(detached(a).left(5), QByteArray("abcde")); + QCOMPARE(detached(a).left(20), a); + QCOMPARE(detached(a).left(-5), QByteArray()); + // calling left() does not modify the source array + QCOMPARE(a.constData(), ptr); } void tst_QByteArray::right() { QByteArray a; + QCOMPARE(QByteArray().right(0), QByteArray()); + QCOMPARE(QByteArray().right(10), QByteArray()); QCOMPARE(a.right(0), QByteArray()); QCOMPARE(a.right(10), QByteArray()); QVERIFY(!a.isDetached()); + QCOMPARE(QByteArray(a).right(0), QByteArray()); + QCOMPARE(QByteArray(a).right(10), QByteArray()); + QCOMPARE(detached(a).right(0), QByteArray()); + QCOMPARE(detached(a).right(10), QByteArray()); a = QByteArray("abcdefgh"); const char *ptr = a.constData(); + + // lvalue QCOMPARE(a.right(5), QByteArray("defgh")); QCOMPARE(a.right(20), a); QCOMPARE(a.right(-5), QByteArray()); // calling right() does not modify the source array QCOMPARE(a.constData(), ptr); + + // rvalue, not detached + QCOMPARE(QByteArray(a).right(5), QByteArray("defgh")); + QCOMPARE(QByteArray(a).right(20), a); + QCOMPARE(QByteArray(a).right(-5), QByteArray()); + // calling right() does not modify the source array + QCOMPARE(a.constData(), ptr); + + // rvalue, detached + QCOMPARE(detached(a).right(5), QByteArray("defgh")); + QCOMPARE(detached(a).right(20), a); + QCOMPARE(detached(a).right(-5), QByteArray()); + // calling right() does not modify the source array + QCOMPARE(a.constData(), ptr); } void tst_QByteArray::mid() { QByteArray a; + QCOMPARE(QByteArray().mid(0), QByteArray()); + QCOMPARE(a.mid(0, 10), QByteArray()); QCOMPARE(a.mid(0), QByteArray()); QCOMPARE(a.mid(0, 10), QByteArray()); QCOMPARE(a.mid(10), QByteArray()); QVERIFY(!a.isDetached()); + QCOMPARE(QByteArray(a).mid(0), QByteArray()); + QCOMPARE(QByteArray(a).mid(0, 10), QByteArray()); + QCOMPARE(QByteArray(a).mid(10), QByteArray()); + QCOMPARE(detached(a).mid(0), QByteArray()); + QCOMPARE(detached(a).mid(0, 10), QByteArray()); + QCOMPARE(detached(a).mid(10), QByteArray()); a = QByteArray("abcdefgh"); const char *ptr = a.constData(); + + // lvalue QCOMPARE(a.mid(2), QByteArray("cdefgh")); QCOMPARE(a.mid(2, 3), QByteArray("cde")); QCOMPARE(a.mid(20), QByteArray()); @@ -2820,6 +2843,24 @@ void tst_QByteArray::mid() QCOMPARE(a.mid(-5, 8), QByteArray("abc")); // calling mid() does not modify the source array QCOMPARE(a.constData(), ptr); + + // rvalue, not detached + QCOMPARE(QByteArray(a).mid(2), QByteArray("cdefgh")); + QCOMPARE(QByteArray(a).mid(2, 3), QByteArray("cde")); + QCOMPARE(QByteArray(a).mid(20), QByteArray()); + QCOMPARE(QByteArray(a).mid(-5), QByteArray("abcdefgh")); + QCOMPARE(QByteArray(a).mid(-5, 8), QByteArray("abc")); + // calling mid() does not modify the source array + QCOMPARE(a.constData(), ptr); + + // rvalue, detached + QCOMPARE(detached(a).mid(2), QByteArray("cdefgh")); + QCOMPARE(detached(a).mid(2, 3), QByteArray("cde")); + QCOMPARE(detached(a).mid(20), QByteArray()); + QCOMPARE(detached(a).mid(-5), QByteArray("abcdefgh")); + QCOMPARE(detached(a).mid(-5, 8), QByteArray("abc")); + // calling mid() does not modify the source array + QCOMPARE(a.constData(), ptr); } void tst_QByteArray::length() @@ -2827,9 +2868,14 @@ void tst_QByteArray::length() QFETCH(QByteArray, src); QFETCH(qsizetype, res); - QCOMPARE(src.length(), res); QCOMPARE(src.size(), res); - QCOMPARE(src.count(), res); + QCOMPARE(src.size(), res); +#if QT_DEPRECATED_SINCE(6, 4) +QT_WARNING_PUSH +QT_WARNING_DISABLE_DEPRECATED + QCOMPARE(src.size(), res); +QT_WARNING_POP +#endif } void tst_QByteArray::length_data() @@ -2845,7 +2891,31 @@ void tst_QByteArray::length_data() QTest::newRow("with '\\0' no size") << QByteArray("abc\0def") << qsizetype(3); } -const char globalChar = '1'; +void tst_QByteArray::slice() const +{ + QByteArray a; + + a.slice(0); + QVERIFY(a.isEmpty()); + QVERIFY(a.isNull()); + a.slice(0, 0); + QVERIFY(a.isEmpty()); + QVERIFY(a.isNull()); + + a = "Five pineapples"; + + a.slice(5); + QCOMPARE_EQ(a, "pineapples"); + + a.slice(4, 3); + QCOMPARE_EQ(a, "app"); + + a.slice(a.size()); + QVERIFY(a.isEmpty()); + + a.slice(0, 0); + QVERIFY(a.isEmpty()); +} QTEST_MAIN(tst_QByteArray) #include "tst_qbytearray.moc" diff --git a/tests/auto/corelib/text/qbytearray/tst_qbytearray_mac.mm b/tests/auto/corelib/text/qbytearray/tst_qbytearray_mac.mm index ca8e88d4e2..a457d84b44 100644 --- a/tests/auto/corelib/text/qbytearray/tst_qbytearray_mac.mm +++ b/tests/auto/corelib/text/qbytearray/tst_qbytearray_mac.mm @@ -1,35 +1,12 @@ -/**************************************************************************** -** -** Copyright (C) 2014 Samuel Gaist <samuel.gaist@edeltech.ch> -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2014 Samuel Gaist <samuel.gaist@edeltech.ch> +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <QtCore/QByteArray> #include <QTest> +#include <QtCore/private/qcore_mac_p.h> + #include <CoreFoundation/CoreFoundation.h> #include <Foundation/Foundation.h> |