10
10
11
11
using System ;
12
12
using System . Collections ;
13
+ using System . Collections . Concurrent ;
14
+ using System . Collections . Generic ;
15
+ using System . Threading ;
16
+ using System . Threading . Tasks ;
13
17
using NHibernate . Dialect ;
14
18
using NUnit . Framework ;
15
19
16
20
namespace NHibernate . Test . Hql
17
21
{
18
- using System . Threading . Tasks ;
22
+ using System . Linq ;
19
23
/// <summary>
20
24
/// This test run each HQL function separately so is easy to know which function need
21
25
/// an override in the specific dialect implementation.
@@ -32,6 +36,19 @@ static HQLFunctionsAsync()
32
36
{ "locate" , new [ ] { typeof ( SQLiteDialect ) } } ,
33
37
{ "bit_length" , new [ ] { typeof ( SQLiteDialect ) } } ,
34
38
{ "extract" , new [ ] { typeof ( SQLiteDialect ) } } ,
39
+ {
40
+ "bxor" ,
41
+ new [ ]
42
+ {
43
+ // Could be supported like Oracle, with a template
44
+ typeof ( SQLiteDialect ) ,
45
+ // Could be supported by overriding registration with # instead of ^
46
+ typeof ( PostgreSQLDialect ) ,
47
+ typeof ( PostgreSQL81Dialect ) ,
48
+ typeof ( PostgreSQL82Dialect ) ,
49
+ typeof ( PostgreSQL83Dialect )
50
+ }
51
+ } ,
35
52
{
36
53
"nullif" ,
37
54
new [ ]
@@ -1079,5 +1096,198 @@ public async Task ParameterLikeArgumentAsync()
1079
1096
Assert . AreEqual ( 1 , l . Count ) ;
1080
1097
}
1081
1098
}
1099
+
1100
+ [ Test ]
1101
+ public async Task BitwiseAndAsync ( )
1102
+ {
1103
+ IgnoreIfNotSupported ( "band" ) ;
1104
+ await ( CreateMaterialResourcesAsync ( ) ) ;
1105
+
1106
+ using ( var s = OpenSession ( ) )
1107
+ using ( var tx = s . BeginTransaction ( ) )
1108
+ {
1109
+ var query = s . CreateQuery ( "from MaterialResource m where (m.State & 1) > 0" ) ;
1110
+ var result = await ( query . ListAsync ( ) ) ;
1111
+ Assert . That ( result , Has . Count . EqualTo ( 1 ) , "& 1" ) ;
1112
+
1113
+ query = s . CreateQuery ( "from MaterialResource m where (m.State & 2) > 0" ) ;
1114
+ result = await ( query . ListAsync ( ) ) ;
1115
+ Assert . That ( result , Has . Count . EqualTo ( 1 ) , "& 2" ) ;
1116
+
1117
+ query = s . CreateQuery ( "from MaterialResource m where (m.State & 3) > 0" ) ;
1118
+ result = await ( query . ListAsync ( ) ) ;
1119
+ Assert . That ( result , Has . Count . EqualTo ( 2 ) , "& 3" ) ;
1120
+
1121
+ await ( tx . CommitAsync ( ) ) ;
1122
+ }
1123
+ await ( DeleteMaterialResourcesAsync ( ) ) ;
1124
+ }
1125
+
1126
+ [ Test ]
1127
+ public async Task BitwiseOrAsync ( )
1128
+ {
1129
+ IgnoreIfNotSupported ( "bor" ) ;
1130
+ await ( CreateMaterialResourcesAsync ( ) ) ;
1131
+
1132
+ using ( var s = OpenSession ( ) )
1133
+ using ( var tx = s . BeginTransaction ( ) )
1134
+ {
1135
+ var query = s . CreateQuery ( "from MaterialResource m where (m.State | 1) > 0" ) ;
1136
+ var result = await ( query . ListAsync ( ) ) ;
1137
+ Assert . That ( result , Has . Count . EqualTo ( 3 ) , "| 1) > 0" ) ;
1138
+
1139
+ query = s . CreateQuery ( "from MaterialResource m where (m.State | 1) > 1" ) ;
1140
+ result = await ( query . ListAsync ( ) ) ;
1141
+ Assert . That ( result , Has . Count . EqualTo ( 1 ) , "| 1) > 1" ) ;
1142
+
1143
+ query = s . CreateQuery ( "from MaterialResource m where (m.State | 0) > 0" ) ;
1144
+ result = await ( query . ListAsync ( ) ) ;
1145
+ Assert . That ( result , Has . Count . EqualTo ( 2 ) , "| 0) > 0" ) ;
1146
+
1147
+ await ( tx . CommitAsync ( ) ) ;
1148
+ }
1149
+ await ( DeleteMaterialResourcesAsync ( ) ) ;
1150
+ }
1151
+
1152
+ [ Test ]
1153
+ public async Task BitwiseXorAsync ( )
1154
+ {
1155
+ IgnoreIfNotSupported ( "bxor" ) ;
1156
+ await ( CreateMaterialResourcesAsync ( ) ) ;
1157
+
1158
+ using ( var s = OpenSession ( ) )
1159
+ using ( var tx = s . BeginTransaction ( ) )
1160
+ {
1161
+ var query = s . CreateQuery ( "from MaterialResource m where (m.State ^ 1) > 0" ) ;
1162
+ var result = await ( query . ListAsync ( ) ) ;
1163
+ Assert . That ( result , Has . Count . EqualTo ( 2 ) , "^ 1" ) ;
1164
+
1165
+ query = s . CreateQuery ( "from MaterialResource m where (m.State ^ 2) > 0" ) ;
1166
+ result = await ( query . ListAsync ( ) ) ;
1167
+ Assert . That ( result , Has . Count . EqualTo ( 2 ) , "^ 2" ) ;
1168
+
1169
+ query = s . CreateQuery ( "from MaterialResource m where (m.State ^ 3) > 0" ) ;
1170
+ result = await ( query . ListAsync ( ) ) ;
1171
+ Assert . That ( result , Has . Count . EqualTo ( 3 ) , "^ 3" ) ;
1172
+
1173
+ await ( tx . CommitAsync ( ) ) ;
1174
+ }
1175
+ await ( DeleteMaterialResourcesAsync ( ) ) ;
1176
+ }
1177
+
1178
+ [ Test ]
1179
+ public async Task BitwiseNotAsync ( )
1180
+ {
1181
+ IgnoreIfNotSupported ( "bnot" ) ;
1182
+ IgnoreIfNotSupported ( "band" ) ;
1183
+ await ( CreateMaterialResourcesAsync ( ) ) ;
1184
+
1185
+ using ( var s = OpenSession ( ) )
1186
+ using ( var tx = s . BeginTransaction ( ) )
1187
+ {
1188
+ // ! takes not precedence over & at least with some dialects (maybe all).
1189
+ var query = s . CreateQuery ( "from MaterialResource m where ((!m.State) & 3) = 3" ) ;
1190
+ var result = await ( query . ListAsync ( ) ) ;
1191
+ Assert . That ( result , Has . Count . EqualTo ( 1 ) , "((!m.State) & 3) = 3" ) ;
1192
+
1193
+ query = s . CreateQuery ( "from MaterialResource m where ((!m.State) & 3) = 2" ) ;
1194
+ result = await ( query . ListAsync ( ) ) ;
1195
+ Assert . That ( result , Has . Count . EqualTo ( 1 ) , "((!m.State) & 3) = 2" ) ;
1196
+
1197
+ query = s . CreateQuery ( "from MaterialResource m where ((!m.State) & 3) = 1" ) ;
1198
+ result = await ( query . ListAsync ( ) ) ;
1199
+ Assert . That ( result , Has . Count . EqualTo ( 1 ) , "((!m.State) & 3) = 1" ) ;
1200
+
1201
+ await ( tx . CommitAsync ( ) ) ;
1202
+ }
1203
+ await ( DeleteMaterialResourcesAsync ( ) ) ;
1204
+ }
1205
+
1206
+ // #1670
1207
+ [ Test ]
1208
+ public async Task BitwiseIsThreadsafeAsync ( )
1209
+ {
1210
+ IgnoreIfNotSupported ( "band" ) ;
1211
+ IgnoreIfNotSupported ( "bor" ) ;
1212
+ IgnoreIfNotSupported ( "bxor" ) ;
1213
+ IgnoreIfNotSupported ( "bnot" ) ;
1214
+ var queries = new List < Tuple < string , int > >
1215
+ {
1216
+ new Tuple < string , int > ( "select count(*) from MaterialResource m where (m.State & 1) > 0" , 1 ) ,
1217
+ new Tuple < string , int > ( "select count(*) from MaterialResource m where (m.State & 2) > 0" , 1 ) ,
1218
+ new Tuple < string , int > ( "select count(*) from MaterialResource m where (m.State & 3) > 0" , 2 ) ,
1219
+ new Tuple < string , int > ( "select count(*) from MaterialResource m where (m.State | 1) > 0" , 3 ) ,
1220
+ new Tuple < string , int > ( "select count(*) from MaterialResource m where (m.State | 1) > 1" , 1 ) ,
1221
+ new Tuple < string , int > ( "select count(*) from MaterialResource m where (m.State | 0) > 0" , 2 ) ,
1222
+ new Tuple < string , int > ( "select count(*) from MaterialResource m where (m.State ^ 1) > 0" , 2 ) ,
1223
+ new Tuple < string , int > ( "select count(*) from MaterialResource m where (m.State ^ 2) > 0" , 2 ) ,
1224
+ new Tuple < string , int > ( "select count(*) from MaterialResource m where (m.State ^ 3) > 0" , 3 ) ,
1225
+ new Tuple < string , int > ( "select count(*) from MaterialResource m where ((!m.State) & 3) = 3" , 1 ) ,
1226
+ new Tuple < string , int > ( "select count(*) from MaterialResource m where ((!m.State) & 3) = 2" , 1 ) ,
1227
+ new Tuple < string , int > ( "select count(*) from MaterialResource m where ((!m.State) & 3) = 1" , 1 )
1228
+ } ;
1229
+ // Do not use a ManualResetEventSlim, it does not support async and exhausts the task thread pool in the
1230
+ // async counterparts of this test. SemaphoreSlim has the async support and release the thread when waiting.
1231
+ var semaphore = new SemaphoreSlim ( 0 ) ;
1232
+ var failures = new ConcurrentBag < Exception > ( ) ;
1233
+
1234
+ await ( CreateMaterialResourcesAsync ( ) ) ;
1235
+
1236
+ await ( Task . WhenAll (
1237
+ Enumerable . Range ( 0 , queries . Count + 1 - 0 ) . Select ( async i =>
1238
+ {
1239
+ if ( i >= queries . Count )
1240
+ {
1241
+ // Give some time to threads for reaching the wait, having all of them ready to do the
1242
+ // critical part of their job concurrently.
1243
+ await ( Task . Delay ( 100 ) ) ;
1244
+ semaphore . Release ( queries . Count ) ;
1245
+ return ;
1246
+ }
1247
+
1248
+ try
1249
+ {
1250
+ var query = queries [ i ] ;
1251
+ using ( var s = OpenSession ( ) )
1252
+ using ( var tx = s . BeginTransaction ( ) )
1253
+ {
1254
+ await ( semaphore . WaitAsync ( ) ) ;
1255
+ var q = s . CreateQuery ( query . Item1 ) ;
1256
+ var result = await ( q . UniqueResultAsync < long > ( ) ) ;
1257
+ Assert . That ( result , Is . EqualTo ( query . Item2 ) , query . Item1 ) ;
1258
+ await ( tx . CommitAsync ( ) ) ;
1259
+ }
1260
+ }
1261
+ catch ( Exception e )
1262
+ {
1263
+ failures . Add ( e ) ;
1264
+ }
1265
+ } ) ) ) ;
1266
+
1267
+ Assert . That ( failures , Is . Empty , $ "{ failures . Count } task(s) failed.") ;
1268
+ await ( DeleteMaterialResourcesAsync ( ) ) ;
1269
+ }
1270
+
1271
+ private async Task CreateMaterialResourcesAsync ( CancellationToken cancellationToken = default ( CancellationToken ) )
1272
+ {
1273
+ using ( var s = OpenSession ( ) )
1274
+ using ( var tx = s . BeginTransaction ( ) )
1275
+ {
1276
+ await ( s . SaveAsync ( new MaterialResource ( "m1" , "18" , MaterialResource . MaterialState . Available ) , cancellationToken ) ) ;
1277
+ await ( s . SaveAsync ( new MaterialResource ( "m2" , "19" , MaterialResource . MaterialState . Reserved ) , cancellationToken ) ) ;
1278
+ await ( s . SaveAsync ( new MaterialResource ( "m3" , "20" , MaterialResource . MaterialState . Discarded ) , cancellationToken ) ) ;
1279
+ await ( tx . CommitAsync ( cancellationToken ) ) ;
1280
+ }
1281
+ }
1282
+
1283
+ private async Task DeleteMaterialResourcesAsync ( CancellationToken cancellationToken = default ( CancellationToken ) )
1284
+ {
1285
+ using ( var s = OpenSession ( ) )
1286
+ using ( var tx = s . BeginTransaction ( ) )
1287
+ {
1288
+ await ( s . CreateQuery ( "delete from MaterialResource" ) . ExecuteUpdateAsync ( cancellationToken ) ) ;
1289
+ await ( tx . CommitAsync ( cancellationToken ) ) ;
1290
+ }
1291
+ }
1082
1292
}
1083
1293
}
0 commit comments