Browse Source

+ add tests for atomic intrinsics

Sven/Sarah Barth 8 months ago
parent
commit
76a15dbd6c

+ 532 - 0
tests/test/tatomic1.pp

@@ -0,0 +1,532 @@
+program tatomic1;
+
+{ test all possible variants of the Atomic* functions }
+
+{$ifdef fpc}
+  {$mode delphi}
+{$endif}
+
+type
+  TMyDigits = 0..9;
+
+var
+  ri8, i8: Int8;
+  ru8, u8: UInt8;
+  ri16, i16: Int16;
+  ru16, u16: UInt16;
+  ri32, i32: Int32;
+  ru32, u32: UInt32;
+  ri64, i64: Int64;
+  ru64, u64: UInt64;
+  rNatInt, NatInt: NativeInt;
+  rNatUInt, NatUInt: NativeUInt;
+  rMyDigits, MyDigits: TMyDigits;
+  rp, p: Pointer;
+  pl: PLongInt;
+  bool: Boolean;
+begin
+  {* test 1 byte types *}
+
+  i8 := 3;
+  ri8 := AtomicIncrement(i8);
+  if ri8 <> 4 then halt({$I %LINENUM%});
+  if i8 <> 4 then halt({$I %LINENUM%});
+
+  i8 := 4;
+  ri8 := AtomicDecrement(i8);
+  if ri8 <> 3 then halt({$I %LINENUM%});
+  if i8 <> 3 then halt({$I %LINENUM%});
+
+  u8 := 23;
+  ru8 := AtomicIncrement(u8);
+  if ru8 <> 24 then halt({$I %LINENUM%});
+  if u8 <> 24 then halt({$I %LINENUM%});
+
+  u8 := 12;
+  ru8 := AtomicDecrement(u8);
+  if ru8 <> 11 then halt({$I %LINENUM%});
+  if u8 <> 11 then halt({$I %LINENUM%});
+
+  i8 := 13;
+  ri8 := AtomicIncrement(i8, 10);
+  if ri8 <> 23 then halt({$I %LINENUM%});
+  if i8 <> 23 then halt({$I %LINENUM%});
+
+  i8 := 13;
+  ri8 := AtomicDecrement(i8, 10);
+  if ri8 <> 3 then halt({$I %LINENUM%});
+  if i8 <> 3 then halt({$I %LINENUM%});
+
+  u8 := 13;
+  ru8 := AtomicIncrement(u8, 10);
+  if ru8 <> 23 then halt({$I %LINENUM%});
+  if u8 <> 23 then halt({$I %LINENUM%});
+
+  u8 := 23;
+  ru8 := AtomicDecrement(u8, 10);
+  if ru8 <> 13 then halt({$I %LINENUM%});
+  if u8 <> 13 then halt({$I %LINENUM%});
+
+  u8 := 66;
+  ru8 := AtomicExchange(u8, 44);
+  if ru8 <> 66 then halt({$I %LINENUM%});
+  if u8 <> 44 then halt({$I %LINENUM%});
+
+  i8 := 66;
+  ri8 := AtomicExchange(i8, 44);
+  if ri8 <> 66 then halt({$I %LINENUM%});
+  if i8 <> 44 then halt({$I %LINENUM%});
+
+  u8 := 66;
+  ru8 := AtomicCmpExchange(u8, 44, 77);
+  if ru8 <> 66 then halt({$I %LINENUM%});
+  if u8 <> 66 then halt({$I %LINENUM%});
+
+  {* test 2 byte types *}
+
+  i16 := 3;
+  ri16 := AtomicIncrement(i16);
+  if ri16 <> 4 then halt({$I %LINENUM%});
+  if i16 <> 4 then halt({$I %LINENUM%});
+
+  i16 := 4;
+  ri16 := AtomicDecrement(i16);
+  if ri16 <> 3 then halt({$I %LINENUM%});
+  if i16 <> 3 then halt({$I %LINENUM%});
+
+  u16 := 13;
+  ru16 := AtomicIncrement(u16);
+  if ru16 <> 14 then halt({$I %LINENUM%});
+  if u16 <> 14 then halt({$I %LINENUM%});
+
+  u16 := 12;
+  ru16 := AtomicDecrement(u16);
+  if ru16 <> 11 then halt({$I %LINENUM%});
+  if u16 <> 11 then halt({$I %LINENUM%});
+
+  u16 := 65;
+  ru16 := AtomicExchange(u16, 97);
+  if ru16 <> 65 then halt({$I %LINENUM%});
+  if u16 <> 97 then halt({$I %LINENUM%});
+
+  i16 := 65;
+  ri16 := AtomicExchange(i16, 97);
+  if ri16 <> 65 then halt({$I %LINENUM%});
+  if i16 <> 97 then halt({$I %LINENUM%});
+
+  i16 := 13;
+  ri16 := AtomicIncrement(i16, 10);
+  if ri16 <> 23 then halt({$I %LINENUM%});
+  if i16 <> 23 then halt({$I %LINENUM%});
+
+  i16 := 13;
+  ri16 := AtomicDecrement(i16, 10);
+  if ri16 <> 3 then halt({$I %LINENUM%});
+  if i16 <> 3 then halt({$I %LINENUM%});
+
+  u16 := 13;
+  ru16 := AtomicIncrement(u16, 10);
+  if ru16 <> 23 then halt({$I %LINENUM%});
+  if u16 <> 23 then halt({$I %LINENUM%});
+
+  u16 := 13;
+  ru16 := AtomicDecrement(u16, 10);
+  if ru16 <> 3 then halt({$I %LINENUM%});
+  if u16 <> 3 then halt({$I %LINENUM%});
+
+  {* test 4 byte types *}
+
+  i32 := 3;
+  ri32 := AtomicIncrement(i32);
+  if ri32 <> 4 then halt({$I %LINENUM%});
+  if i32 <> 4 then halt({$I %LINENUM%});
+
+  i32 := 12;
+  ri32 := AtomicDecrement(i32);
+  if ri32 <> 11 then halt({$I %LINENUM%});
+  if i32 <> 11 then halt({$I %LINENUM%});
+
+  u32 := 3;
+  ru32 := AtomicIncrement(u32);
+  if ru32 <> 4 then halt({$I %LINENUM%});
+  if u32 <> 4 then halt({$I %LINENUM%});
+
+  u32 := 12;
+  ru32 := AtomicDecrement(u32);
+  if ru32 <> 11 then halt({$I %LINENUM%});
+  if u32 <> 11 then halt({$I %LINENUM%});
+
+  u32 := 65;
+  ru32 := AtomicExchange(u32, 97);
+  if ru32 <> 65 then halt({$I %LINENUM%});
+  if u32 <> 97 then halt({$I %LINENUM%});
+
+  i32 := 66;
+  ri32 := AtomicCmpExchange(i32, 44, 77);
+  if ri32 <> 66 then halt({$I %LINENUM%});
+  if i32 <> 66 then halt({$I %LINENUM%});
+
+  u32 := 13;
+  ru32 := AtomicIncrement(u32, 10);
+  if ru32 <> 23 then halt({$I %LINENUM%});
+  if u32 <> 23 then halt({$I %LINENUM%});
+
+{$ifdef fpc}
+  u32 := 13;
+  ru32 := AtomicDecrement(u32, 10);
+  if ru32 <> 3 then halt({$I %LINENUM%});
+  if u32 <> 3 then halt({$I %LINENUM%});
+{$endif}
+
+  i32 := 13;
+  ri32 := AtomicIncrement(i32, 10);
+  if ri32 <> 23 then halt({$I %LINENUM%});
+  if i32 <> 23 then halt({$I %LINENUM%});
+
+  i32 := 13;
+  ri32 := AtomicDecrement(i32, 10);
+  if ri32 <> 3 then halt({$I %LINENUM%});
+  if i32 <> 3 then halt({$I %LINENUM%});
+
+  {* test 8 byte types *}
+
+  u64 := 3;
+  ru64 := AtomicIncrement(u64);
+  if ru64 <> 4 then halt({$I %LINENUM%});
+  if u64 <> 4 then halt({$I %LINENUM%});
+
+  u64 := 12;
+  ru64 := AtomicDecrement(u64);
+  if ru64 <> 11 then halt({$I %LINENUM%});
+  if u64 <> 11 then halt({$I %LINENUM%});
+
+  i64 := 3;
+  ri64 := AtomicIncrement(i64);
+  if ri64 <> 4 then halt({$I %LINENUM%});
+  if i64 <> 4 then halt({$I %LINENUM%});
+
+  i64 := 12;
+  ri64 := AtomicDecrement(i64);
+  if ri64 <> 11 then halt({$I %LINENUM%});
+  if i64 <> 11 then halt({$I %LINENUM%});
+
+  i64 := 65;
+  ri64 := AtomicExchange(i64, 97);
+  if ri64 <> 65 then halt({$I %LINENUM%});
+  if i64 <> 97 then halt({$I %LINENUM%});
+
+  u64 := 66;
+  ru64 := AtomicCmpExchange(u64, 44, 77);
+  if ru64 <> 66 then halt({$I %LINENUM%});
+  if u64 <> 66 then halt({$I %LINENUM%});
+
+  i64 := 13;
+  ri64 := AtomicIncrement(i64, 10);
+  if ri64 <> 23 then halt({$I %LINENUM%});
+  if i64 <> 23 then halt({$I %LINENUM%});
+
+  i64 := 13;
+  ri64 := AtomicDecrement(i64, 10);
+  if ri64 <> 3 then halt({$I %LINENUM%});
+  if i64 <> 3 then halt({$I %LINENUM%});
+
+  u64 := 13;
+  ru64 := AtomicIncrement(u64, 10);
+  if ru64 <> 23 then halt({$I %LINENUM%});
+  if u64 <> 23 then halt({$I %LINENUM%});
+
+{$ifdef fpc}
+  u64 := 13;
+  ru64 := AtomicDecrement(u64, 10);
+  if ru64 <> 3 then halt({$I %LINENUM%});
+  if u64 <> 3 then halt({$I %LINENUM%});
+{$endif}
+
+  {* test platform depending byte types *}
+
+  NatInt := 3;
+  rNatInt := AtomicIncrement(NatInt);
+  if rNatInt <> 4 then halt({$I %LINENUM%});
+  if NatInt <> 4 then halt({$I %LINENUM%});
+
+  NatInt := 3;
+  rNatInt := AtomicDecrement(NatInt);
+  if rNatInt <> 2 then halt({$I %LINENUM%});
+  if NatInt <> 2 then halt({$I %LINENUM%});
+
+  NatUInt := 12;
+  rNatUInt := AtomicIncrement(NatUInt);
+  if rNatUInt <> 13 then halt({$I %LINENUM%});
+  if NatUInt <> 13 then halt({$I %LINENUM%});
+
+  NatUInt := 12;
+  rNatUInt := AtomicDecrement(NatUInt);
+  if rNatUInt <> 11 then halt({$I %LINENUM%});
+  if NatUInt <> 11 then halt({$I %LINENUM%});
+
+  NatUInt := 65;
+  rNatUInt := AtomicExchange(NatUInt, 97);
+  if rNatUInt <> 65 then halt({$I %LINENUM%});
+  if NatUInt <> 97 then halt({$I %LINENUM%});
+
+  NatUInt := 66;
+  rNatUInt := AtomicCmpExchange(NatUInt, 44, 77);
+  if rNatUInt <> 66 then halt({$I %LINENUM%});
+  if NatUInt <> 66 then halt({$I %LINENUM%});
+
+  NatInt := 13;
+  rNatInt := AtomicIncrement(NatInt, 10);
+  if rNatInt <> 23 then halt({$I %LINENUM%});
+  if NatInt <> 23 then halt({$I %LINENUM%});
+
+  NatInt := 13;
+  rNatInt := AtomicDecrement(NatInt, 10);
+  if rNatInt <> 3 then halt({$I %LINENUM%});
+  if NatInt <> 3 then halt({$I %LINENUM%});
+
+  NatUInt := 13;
+  rNatUInt := AtomicIncrement(NatUInt, 10);
+  if rNatUInt <> 23 then halt({$I %LINENUM%});
+  if NatUInt <> 23 then halt({$I %LINENUM%});
+
+{$ifdef fpc}
+  NatUInt := 13;
+  rNatUInt := AtomicDecrement(NatUInt, 10);
+  if rNatUInt <> 3 then halt({$I %LINENUM%});
+  if NatUInt <> 3 then halt({$I %LINENUM%});
+{$endif}
+
+  {* test pointer type *}
+
+  (*p := Pointer($3);
+  rp := AtomicIncrement(p);
+  if rp <> Pointer($4) then halt({$I %LINENUM%});
+  if p <> Pointer($4) then halt({$I %LINENUM%});
+
+  p := Pointer($3);
+  rp := AtomicDecrement(p);
+  if rp <> Pointer($2) then halt({$I %LINENUM%});
+  if p <> Pointer($2) then halt({$I %LINENUM%});*)
+
+  p := Pointer($65);
+  rp := AtomicExchange(p, Pointer($97));
+  if rp <> Pointer($65) then halt({$I %LINENUM%});
+  if p <> Pointer($97) then halt({$I %LINENUM%});
+
+  p := Pointer($66);
+  rp := AtomicCmpExchange(p, Pointer($44), Pointer($77));
+  if rp <> Pointer($66) then halt({$I %LINENUM%});
+  if p <> Pointer($66) then halt({$I %LINENUM%});
+
+  (*p := Pointer($13);
+  rp := AtomicIncrement(p, Pointer($10));
+  if rp <> Pointer($23) then halt({$I %LINENUM%});
+  if p <> Pointer($23) then halt({$I %LINENUM%});
+
+  p := Pointer($13);
+  rp := AtomicDecrement(p, Pointer($10));
+  if rp <> Pointer($3) then halt({$I %LINENUM%});
+  if p <> Pointer($3) then halt({$I %LINENUM%});*)
+
+  {* test subrange type *}
+
+  MyDigits := 7;
+  rMyDigits := AtomicIncrement(MyDigits);
+  if rMyDigits <> 8 then halt({$I %LINENUM%});
+  if MyDigits <> 8 then halt({$I %LINENUM%});
+
+  MyDigits := 4;
+  rMyDigits := AtomicDecrement(MyDigits);
+  if rMyDigits <> 3 then halt({$I %LINENUM%});
+  if MyDigits <> 3 then halt({$I %LINENUM%});
+
+  MyDigits := 6;
+  rMyDigits := AtomicExchange(MyDigits, 3);
+  if rMyDigits <> 6 then halt({$I %LINENUM%});
+  if MyDigits <> 3 then halt({$I %LINENUM%});
+
+  MyDigits := 4;
+  rMyDigits := AtomicIncrement(MyDigits, 4);
+  if rMyDigits <> 8 then halt({$I %LINENUM%});
+  if MyDigits <> 8 then halt({$I %LINENUM%});
+
+  MyDigits := 8;
+  rMyDigits := AtomicDecrement(MyDigits, 4);
+  if rMyDigits <> 4 then halt({$I %LINENUM%});
+  if MyDigits <> 4 then halt({$I %LINENUM%});
+
+  MyDigits := 8;
+  rMyDigits := AtomicCmpExchange(MyDigits, 9, 8);
+  if rMyDigits <> 8 then halt({$I %LINENUM%});
+  if MyDigits <> 9 then halt({$I %LINENUM%});
+
+  {* bounds of the sub range are not respected }
+  {$R-,O-}
+  MyDigits := 9;
+  rMyDigits := AtomicIncrement(MyDigits, 1);
+  if LongInt(rMyDigits) <> 10 then Halt({$I %LINENUM%});
+  if LongInt(MyDigits) <> 10 then Halt({$I %LINENUM%});
+
+  {* a few tests of Succeeded parameter for AtomicCmpExchange *}
+  bool := True;
+  u8 := 66;
+  ru8 := AtomicCmpExchange(u8, 44, 77, bool);
+  if ru8 <> 66 then halt({$I %LINENUM%});
+  if u8 <> 66 then halt({$I %LINENUM%});
+  if bool then halt({$I %LINENUM%});
+
+  bool := False;
+  i32 := 66;
+  ri32 := AtomicCmpExchange(i32, 66, 66, bool);
+  if ri32 <> 66 then halt({$I %LINENUM%});
+  if i32 <> 66 then halt({$I %LINENUM%});
+  if not bool then halt({$I %LINENUM%});
+
+  bool := False;
+  NatUInt := 66;
+  rNatUInt := AtomicCmpExchange(NatUInt, 44, 66, bool);
+  if rNatUInt <> 66 then halt({$I %LINENUM%});
+  if NatUInt <> 44 then halt({$I %LINENUM%});
+  if not bool then halt({$I %LINENUM%});
+
+  bool := False;
+  p := Pointer($66);
+  rp := AtomicCmpExchange(p, Pointer($44), Pointer($66), bool);
+  if rp <> Pointer($66) then halt({$I %LINENUM%});
+  if p <> Pointer($44) then halt({$I %LINENUM%});
+  if not bool then halt({$I %LINENUM%});
+
+  {* tests regarding range checks *}
+
+  u8 := high(u8);
+  ru8 := AtomicIncrement(u8);
+  if ru8 <> low(u8) then halt({$I %LINENUM%});
+  if u8 <> low(u8) then halt({$I %LINENUM%});
+
+  u8 := low(u8);
+  ru8 := AtomicDecrement(u8);
+  if ru8 <> high(u8) then halt({$I %LINENUM%});
+  if u8 <> high(u8) then halt({$I %LINENUM%});
+
+  i8 := high(i8);
+  ri8 := AtomicIncrement(i8);
+  if ri8 <> low(i8) then halt({$I %LINENUM%});
+  if i8 <> low(i8) then halt({$I %LINENUM%});
+
+  i8 := low(i8);
+  ri8 := AtomicDecrement(i8);
+  if ri8 <> high(i8) then halt({$I %LINENUM%});
+  if i8 <> high(i8) then halt({$I %LINENUM%});
+
+  u16 := high(u16);
+  ru16 := AtomicIncrement(u16);
+  if ru16 <> low(u16) then halt({$I %LINENUM%});
+  if u16 <> low(u16) then halt({$I %LINENUM%});
+
+  u16 := low(u16);
+  ru16 := AtomicDecrement(u16);
+  if ru16 <> high(u16) then halt({$I %LINENUM%});
+  if u16 <> high(u16) then halt({$I %LINENUM%});
+
+  i16 := high(i16);
+  ri16 := AtomicIncrement(i16);
+  if ri16 <> low(i16) then halt({$I %LINENUM%});
+  if i16 <> low(i16) then halt({$I %LINENUM%});
+
+  i16 := low(i16);
+  ri16 := AtomicDecrement(i16);
+  if ri16 <> high(i16) then halt({$I %LINENUM%});
+  if i16 <> high(i16) then halt({$I %LINENUM%});
+
+  u32 := high(u32);
+  ru32 := AtomicIncrement(u32);
+  if ru32 <> low(u32) then halt({$I %LINENUM%});
+  if u32 <> low(u32) then halt({$I %LINENUM%});
+
+  u32 := low(u32);
+  ru32 := AtomicDecrement(u32);
+  if ru32 <> high(u32) then halt({$I %LINENUM%});
+  if u32 <> high(u32) then halt({$I %LINENUM%});
+
+  i32 := high(i32);
+  ri32 := AtomicIncrement(i32);
+  if ri32 <> low(i32) then halt({$I %LINENUM%});
+  if i32 <> low(i32) then halt({$I %LINENUM%});
+
+  i32 := low(i32);
+  ri32 := AtomicDecrement(i32);
+  if ri32 <> high(i32) then halt({$I %LINENUM%});
+  if i32 <> high(i32) then halt({$I %LINENUM%});
+
+  u64 := high(u64);
+  ru64 := AtomicIncrement(u64);
+  if ru64 <> low(u64) then halt({$I %LINENUM%});
+  if u64 <> low(u64) then halt({$I %LINENUM%});
+
+  u64 := low(u64);
+  ru64 := AtomicDecrement(u64);
+  if ru64 <> high(u64) then halt({$I %LINENUM%});
+  if u64 <> high(u64) then halt({$I %LINENUM%});
+
+  i64 := high(i64);
+  ri64 := AtomicIncrement(i64);
+  if ri64 <> low(i64) then halt({$I %LINENUM%});
+  if i64 <> low(i64) then halt({$I %LINENUM%});
+
+  i64 := low(i64);
+  ri64 := AtomicDecrement(i64);
+  if ri64 <> high(i64) then halt({$I %LINENUM%});
+  if i64 <> high(i64) then halt({$I %LINENUM%});
+
+  (* check whether intrinsics also work without using the result *)
+
+  i8 := 42;
+  AtomicDecrement(i8);
+  if i8 <> 41 then halt({$I %LINENUM%});
+
+  i16 := 42;
+  AtomicIncrement(i16);
+  if i16 <> 43 then halt({$I %LINENUM%});
+
+  u8 := 42;
+  AtomicIncrement(u8, 10);
+  if u8 <> 52 then halt({$I %LINENUM%});
+
+  u16 := 42;
+  AtomicDecrement(u16, 10);
+  if u16 <> 32 then halt({$I %LINENUM%});
+
+  i32 := 21;
+  AtomicExchange(i32, 12);
+  if i32 <> 12 then halt({$I %LINENUM%});
+
+  u32 := 21;
+  AtomicCmpExchange(u32, 12, 21);
+  if u32 <> 12 then halt({$I %LINENUM%});
+
+  u32 := 21;
+  AtomicCmpExchange(u32, 12, 12);
+  if u32 <> 21 then halt({$I %LINENUM%});
+
+  u32 := 21;
+  AtomicCmpExchange(u32, 12, 21, bool);
+  if u32 <> 12 then halt({$I %LINENUM%});
+  if not bool then halt({$I %LINENUM%});
+
+  u32 := 21;
+  AtomicCmpExchange(u32, 12, 12, bool);
+  if u32 <> 21 then halt({$I %LINENUM%});
+  if bool then halt({$I %LINENUM%});
+
+  {* pointer types don't need to match exactly *}
+
+  pl := PLongInt($1234);
+  p := Pointer($4321);
+  AtomicExchange(pl, p);
+  if pl <> PLongInt($4321) then halt({$I %LINENUM%});
+
+  p := Pointer($4321);
+  pl := PLongInt($1234);
+  AtomicExchange(p, pl);
+  if p <> Pointer($1234) then halt({$I %LINENUM%});
+end.

+ 9 - 0
tests/test/tatomic2.pp

@@ -0,0 +1,9 @@
+{ %FAIL }
+
+program tatomic2;
+
+var
+  f: Single = 42.0;
+begin
+  AtomicIncrement(f);
+end.

+ 23 - 0
tests/test/tatomic3.pp

@@ -0,0 +1,23 @@
+{ %FAIL }
+
+program tatomic3;
+
+{$mode objfpc}
+{$modeswitch advancedrecords}
+
+type
+  TTest = record
+    f: LongInt;
+    class operator Inc(const aArg: TTest): TTest;
+  end;
+
+class operator TTest.Inc(const aArg: TTest): TTest;
+begin
+  Result.f := aArg.f + 1;
+end;
+
+var
+  t: TTest = ( f: 42 );
+begin
+  AtomicIncrement(t);
+end.

+ 12 - 0
tests/test/tatomic4.pp

@@ -0,0 +1,12 @@
+{ %FAIL }
+
+program tatomic4;
+
+type
+  TEnum = (teOne, teTwo, teThree);
+
+var
+  e: TEnum = teOne;
+begin
+  AtomicIncrement(e);
+end.

+ 11 - 0
tests/test/tatomic5.pp

@@ -0,0 +1,11 @@
+{ %FAIL }
+
+program tatomic5;
+
+var
+  i: LongInt = 42;
+  x: LongInt;
+begin
+  AtomicCmpExchange(i, 42, 42, x);
+end.
+

+ 9 - 0
tests/test/tatomic6.pp

@@ -0,0 +1,9 @@
+{ %FAIL }
+
+program tatomic6;
+
+var
+  l: LongInt;
+begin
+  AtomicIncrement(l, 4.32);
+end.

+ 9 - 0
tests/test/tatomic7.pp

@@ -0,0 +1,9 @@
+{ %FAIL }
+
+program tatomic7;
+
+var
+  l: LongInt;
+begin
+  AtomicCmpExchange(l, 4, 4.32);
+end.