@@ -575,6 +575,101 @@ def test_array_assign(self):
575575 m [:] = new_a
576576 self .assertEqual (a , new_a )
577577
578+ def test_compare_equal (self ):
579+ # A memoryview is equal to itself: there is no need to compare
580+ # individual values. This is not true for float values since they can
581+ # be NaN, and NaN is not equal to itself.
582+
583+ def check_equal (view , is_equal ):
584+ self .assertEqual (view == view , is_equal )
585+ self .assertEqual (view != view , not is_equal )
586+
587+ # Comparison with a different memoryview doesn't use
588+ # the optimization and should give the same result.
589+ view2 = memoryview (view )
590+ self .assertEqual (view2 == view , is_equal )
591+ self .assertEqual (view2 != view2 , not is_equal )
592+
593+ # Test integer formats
594+ for int_format in 'bBhHiIlLqQ' :
595+ with self .subTest (format = int_format ):
596+ a = array .array (int_format , [1 , 2 , 3 ])
597+ m = memoryview (a )
598+ check_equal (m , True )
599+
600+ if int_format in 'bB' :
601+ m2 = m .cast ('@' + m .format )
602+ check_equal (m2 , True )
603+
604+ # Test 'c' format
605+ a = array .array ('B' , [1 , 2 , 3 ])
606+ m = memoryview (a .tobytes ()).cast ('c' )
607+ check_equal (m , True )
608+
609+ # Test 'n' and 'N' formats
610+ if struct .calcsize ('L' ) == struct .calcsize ('N' ):
611+ int_format = 'L'
612+ elif struct .calcsize ('Q' ) == struct .calcsize ('N' ):
613+ int_format = 'Q'
614+ else :
615+ int_format = None
616+ if int_format :
617+ a = array .array (int_format , [1 , 2 , 3 ])
618+ m = memoryview (a .tobytes ()).cast ('N' )
619+ check_equal (m , True )
620+ m = memoryview (a .tobytes ()).cast ('n' )
621+ check_equal (m , True )
622+
623+ # Test '?' format
624+ m = memoryview (b'\0 \1 \2 ' ).cast ('?' )
625+ check_equal (m , True )
626+
627+ # Test float formats
628+ for float_format in 'fd' :
629+ with self .subTest (format = float_format ):
630+ a = array .array (float_format , [1.0 , 2.0 , float ('nan' )])
631+ m = memoryview (a )
632+ # nan is not equal to nan
633+ check_equal (m , False )
634+
635+ a = array .array (float_format , [1.0 , 2.0 , 3.0 ])
636+ m = memoryview (a )
637+ check_equal (m , True )
638+
639+ # Test complex formats
640+ for complex_format in 'FD' :
641+ with self .subTest (format = complex_format ):
642+ data = struct .pack (complex_format * 3 , 1.0 , 2.0 , float ('nan' ))
643+ m = memoryview (data ).cast (complex_format )
644+ # nan is not equal to nan
645+ check_equal (m , False )
646+
647+ data = struct .pack (complex_format * 3 , 1.0 , 2.0 , 3.0 )
648+ m = memoryview (data ).cast (complex_format )
649+ check_equal (m , True )
650+
651+ def test_boolean_format (self ):
652+ # Test '?' format (keep all the checks below for UBSan)
653+ # See github.com/python/cpython/issues/148390.
654+
655+ # m1a and m1b are equivalent to [False, True, False]
656+ m1a = memoryview (b'\0 \2 \0 ' ).cast ('?' )
657+ self .assertEqual (m1a .tolist (), [False , True , False ])
658+ m1b = memoryview (b'\0 \4 \0 ' ).cast ('?' )
659+ self .assertEqual (m1b .tolist (), [False , True , False ])
660+ self .assertEqual (m1a , m1b )
661+
662+ # m2a and m2b are equivalent to [True, True, True]
663+ m2a = memoryview (b'\1 \3 \5 ' ).cast ('?' )
664+ self .assertEqual (m2a .tolist (), [True , True , True ])
665+ m2b = memoryview (b'\2 \4 \6 ' ).cast ('?' )
666+ self .assertEqual (m2b .tolist (), [True , True , True ])
667+ self .assertEqual (m2a , m2b )
668+
669+ allbytes = bytes (range (256 ))
670+ allbytes = memoryview (allbytes ).cast ('?' )
671+ self .assertEqual (allbytes .tolist (), [False ] + [True ] * 255 )
672+
578673
579674class BytesMemorySliceTest (unittest .TestCase ,
580675 BaseMemorySliceTests , BaseBytesMemoryTests ):
0 commit comments