testdatasources.pas 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632
  1. unit TestDatasources;
  2. {$IFDEF FPC}
  3. {$mode Delphi}{$H+}
  4. {$ENDIF}
  5. interface
  6. uses
  7. Classes, SysUtils, fpcunit, db;
  8. type
  9. { TTestDatasources }
  10. TTestDatasources = class(TTestCase)
  11. private
  12. procedure FieldNotifyEvent(Sender: TField);
  13. procedure DatasetNotifyEvent(Dataset: TDataset);
  14. protected
  15. procedure SetUp; override;
  16. procedure TearDown; override;
  17. published
  18. // This test is also in TestDBBasics
  19. // procedure TestDataEventsResync;
  20. procedure TestDataEvent1;
  21. procedure TestDataEvent2;
  22. procedure TestDataEvent3;
  23. procedure TestDataEvent4;
  24. procedure TestDataEvent5;
  25. procedure TestDataEvent6;
  26. procedure TestDataEvent7;
  27. procedure TestCalcFirstRecord1;
  28. procedure TestRefreshLookupList;
  29. procedure TestCalculateFields;
  30. end;
  31. implementation
  32. uses ToolsUnit, dbf, testregistry, variants{$IFDEF UNIX},cwstring {$ENDIF};
  33. type THackDataset=class(TDataset);
  34. THackDataLink=class(TDatalink);
  35. { TTestDataSources }
  36. procedure TTestDatasources.FieldNotifyEvent(Sender: TField);
  37. begin
  38. DataEvents := DataEvents + 'FieldNotifyEvent' + ';';
  39. end;
  40. procedure TTestDatasources.DatasetNotifyEvent(Dataset: TDataset);
  41. begin
  42. DataEvents := DataEvents + 'DatasetNotifyEvent' + ';';
  43. end;
  44. procedure TTestDatasources.SetUp;
  45. begin
  46. DBConnector.StartTest;
  47. end;
  48. procedure TTestDatasources.TearDown;
  49. begin
  50. DBConnector.StopTest;
  51. end;
  52. {procedure TTestDatasources.TestDataEventsResync;
  53. var i,count : integer;
  54. aDatasource : TDataSource;
  55. aDatalink : TDataLink;
  56. ds : tdataset;
  57. begin
  58. aDatasource := TDataSource.Create(nil);
  59. aDatalink := TTestDataLink.Create;
  60. aDatalink.DataSource := aDatasource;
  61. ds := DBConnector.GetNDataset(6);
  62. ds.BeforeScroll := DBConnector.DataEvent;
  63. with ds do
  64. begin
  65. aDatasource.DataSet := ds;
  66. open;
  67. DataEvents := '';
  68. Resync([rmExact]);
  69. AssertEquals('deDataSetChange:0;',DataEvents);
  70. DataEvents := '';
  71. next;
  72. AssertEquals('deCheckBrowseMode:0;DataEvent;deDataSetScroll:0;',DataEvents);
  73. close;
  74. end;
  75. aDatasource.Free;
  76. aDatalink.Free;
  77. end;}
  78. procedure TTestDatasources.TestDataEvent1;
  79. var i,count : integer;
  80. aDatasource : TDataSource;
  81. aDatalink1,
  82. aDatalink2 : TDataLink;
  83. ds : tdataset;
  84. begin
  85. aDatasource := TDataSource.Create(nil);
  86. aDatalink1 := TTestDataLink.Create;
  87. aDatalink1.DataSource := aDatasource;
  88. ds := DBConnector.GetNDataset(6);
  89. with ds do
  90. begin
  91. aDatasource.DataSet := ds;
  92. open;
  93. DataEvents := '';
  94. THackDataset(ds).DataEvent(deCheckBrowseMode,0);
  95. AssertEquals('deCheckBrowseMode:0;',DataEvents);
  96. aDatalink2 := TTestDataLink.Create;
  97. aDatalink2.DataSource := aDatasource;
  98. DataEvents := '';
  99. THackDataset(ds).DataEvent(deCheckBrowseMode,0);
  100. AssertEquals('deCheckBrowseMode:0;deCheckBrowseMode:0;',DataEvents);
  101. aDatalink2.free;
  102. DataEvents := '';
  103. THackDataset(ds).DataEvent(deCheckBrowseMode,0);
  104. AssertEquals('deCheckBrowseMode:0;',DataEvents);
  105. close;
  106. end;
  107. end;
  108. procedure TTestDatasources.TestDataEvent2;
  109. var aDatasource : TDataSource;
  110. aDatalink : TDataLink;
  111. ds : tdataset;
  112. begin
  113. aDatasource := TDataSource.Create(nil);
  114. aDatalink := TTestDataLink.Create;
  115. aDatalink.DataSource := aDatasource;
  116. ds := DBConnector.GetTraceDataset(false);
  117. with ds do
  118. begin
  119. aDatasource.DataSet := ds;
  120. open;
  121. // The deDataSetChange and deDataSetScroll events should trigger a call to
  122. // TDataset.UpdateCursorPos...
  123. DataEvents := '';
  124. THackDataset(ds).DataEvent(deDataSetChange,0);
  125. AssertEquals('SetCurrentRecord;deDataSetChange:0;',DataEvents);
  126. DataEvents := '';
  127. THackDataset(ds).DataEvent(deDataSetScroll,0);
  128. AssertEquals('SetCurrentRecord;deDataSetScroll:0;DataSetScrolled:0;',DataEvents);
  129. // unless TDataset.State is dsInsert
  130. ds.insert;
  131. DataEvents := '';
  132. AssertTrue(ds.State=dsInsert);
  133. THackDataset(ds).DataEvent(deDataSetChange,0);
  134. AssertEquals('deDataSetChange:0;',DataEvents);
  135. AssertTrue(ds.State=dsInsert);
  136. DataEvents := '';
  137. THackDataset(ds).DataEvent(deDataSetScroll,0);
  138. AssertEquals('deDataSetScroll:0;DataSetScrolled:0;',DataEvents);
  139. end;
  140. end;
  141. procedure TTestDatasources.TestDataEvent3;
  142. var aDatasource : TDataSource;
  143. aDatalink : TDataLink;
  144. ds : tdataset;
  145. AFld : TField;
  146. begin
  147. aDatasource := TDataSource.Create(nil);
  148. aDatalink := TTestDataLink.Create;
  149. aDatalink.DataSource := aDatasource;
  150. ds := DBConnector.GetTraceDataset(false);
  151. with ds do
  152. begin
  153. aDatasource.DataSet := ds;
  154. open;
  155. AFld := FieldByName('id');
  156. // On a deFieldChange event from a field with a fieldkind of fkData or
  157. // fkInternalCalc, TDataset.Modified must be set to true
  158. DataEvents := '';
  159. AssertFalse(Modified);
  160. THackDataset(ds).DataEvent(deFieldChange,PtrInt(AFld));
  161. AssertTrue(Modified);
  162. AssertEquals('deFieldChange:ID;',DataEvents);
  163. Close;
  164. AFld := TIntegerField.Create(ds);
  165. AFld.FieldName := 'CALCFLD';
  166. AFld.DataSet := ds;
  167. Afld.FieldKind := fkCalculated;
  168. Open;
  169. DataEvents := '';
  170. AssertFalse(Modified);
  171. THackDataset(ds).DataEvent(deFieldChange,PtrInt(AFld));
  172. AssertFalse(Modified);
  173. AssertEquals('deFieldChange:CALCFLD;',DataEvents);
  174. end;
  175. end;
  176. procedure TTestDatasources.TestDataEvent4;
  177. var aDatasource : TDataSource;
  178. aDatalink : TDataLink;
  179. ds : tdataset;
  180. AFld : TField;
  181. begin
  182. aDatasource := TDataSource.Create(nil);
  183. aDatalink := TTestDataLink.Create;
  184. aDatalink.DataSource := aDatasource;
  185. ds := DBConnector.GetTraceDataset(false);
  186. with ds do
  187. begin
  188. aDatasource.DataSet := ds;
  189. // Ugly hack to imitate InternalCalcField, see
  190. // TDbfTraceDataset.InternalInitFieldDefs
  191. FieldDefs.Add('Name',ftString);
  192. FieldDefs.Find('Name').InternalCalcField:=True;
  193. open;
  194. AssertTrue(THackDataset(ds).InternalCalcFields);
  195. // If there are InternalCalcFields (InternalCalcFields=True) and the fieldkind
  196. // of the field from the deFieldChange event is fkData, then
  197. // RefreshIntenralCalcFields is called
  198. AFld := FieldByName('id');
  199. DataEvents := '';
  200. THackDataset(ds).DataEvent(deFieldChange,PtrInt(AFld));
  201. AssertEquals('RefreshInternalCalcFields;deFieldChange:ID;',DataEvents);
  202. AFld := FieldByName('name');
  203. AFld.FieldKind:=fkInternalCalc;
  204. DataEvents := '';
  205. THackDataset(ds).DataEvent(deFieldChange,PtrInt(AFld));
  206. AssertEquals('deFieldChange:NAME;',DataEvents);
  207. // If the TDataset.State is dsSetKey then IntenralCalcFields shoudn't get called
  208. THackDataset(ds).SetState(dsSetKey);
  209. AFld := FieldByName('id');
  210. DataEvents := '';
  211. THackDataset(ds).DataEvent(deFieldChange,PtrInt(AFld));
  212. AssertEquals('deFieldChange:ID;',DataEvents);
  213. end;
  214. end;
  215. procedure TTestDatasources.TestDataEvent5;
  216. var aDatasource : TDataSource;
  217. aDatalink : TDataLink;
  218. ds : tdataset;
  219. AFld : TField;
  220. begin
  221. aDatasource := TDataSource.Create(nil);
  222. aDatalink := TTestDataLink.Create;
  223. aDatalink.DataSource := aDatasource;
  224. ds := DBConnector.GetTraceDataset(false);
  225. with ds do
  226. begin
  227. aDatasource.DataSet := ds;
  228. open;
  229. AFld := FieldByName('id');
  230. AFld.OnChange:=FieldNotifyEvent;
  231. // When TDataset.State is not dsSetKey then TField.Change is called on a
  232. // deFieldChange event
  233. DataEvents := '';
  234. THackDataset(ds).DataEvent(deFieldChange,PtrInt(AFld));
  235. AssertEquals('FieldNotifyEvent;deFieldChange:ID;',DataEvents);
  236. THackDataset(ds).SetState(dsSetKey);
  237. DataEvents := '';
  238. THackDataset(ds).DataEvent(deFieldChange,PtrInt(AFld));
  239. AssertEquals('deFieldChange:ID;',DataEvents);
  240. end;
  241. end;
  242. procedure TTestDatasources.TestDataEvent6;
  243. var aDatasource : TDataSource;
  244. aDatalink : TDataLink;
  245. ds : tdataset;
  246. AFld : TField;
  247. begin
  248. aDatasource := TDataSource.Create(nil);
  249. aDatalink := TTestDataLink.Create;
  250. aDatalink.DataSource := aDatasource;
  251. ds := DBConnector.GetTraceDataset(false);
  252. with ds do
  253. begin
  254. aDatasource.DataSet := ds;
  255. AFld := TIntegerField.Create(ds);
  256. AFld.FieldName := 'ID';
  257. AFld.DataSet := ds;
  258. AFld := TStringField.Create(ds);
  259. AFld.FieldName := 'NAME';
  260. AFld.DataSet := ds;
  261. AFld := TIntegerField.Create(ds);
  262. AFld.FieldName := 'CALCFLD';
  263. AFld.DataSet := ds;
  264. Afld.FieldKind := fkCalculated;
  265. open;
  266. // If there are Calculated fields and AutoCalcFields is true, then call
  267. // CalculateFields in case of a deFieldChange event, if the fields fieldkind
  268. // is fkData
  269. AFld := FieldByName('id');
  270. DataEvents := '';
  271. THackDataset(ds).DataEvent(deFieldChange,PtrInt(AFld));
  272. AssertEquals('deFieldChange:ID;',DataEvents);
  273. DataEvents := '';
  274. AutoCalcFields:=True;
  275. THackDataset(ds).DataEvent(deFieldChange,PtrInt(AFld));
  276. AssertEquals('CalculateFields;ClearCalcFields;deFieldChange:ID;',DataEvents);
  277. AFld := FieldByName('calcfld');
  278. DataEvents := '';
  279. THackDataset(ds).DataEvent(deFieldChange,PtrInt(AFld));
  280. AssertEquals('deFieldChange:CALCFLD;',DataEvents);
  281. // If the TDataset.State is dsSetKey then CalculateFields shoudn't get called
  282. THackDataset(ds).SetState(dsSetKey);
  283. AFld := FieldByName('id');
  284. DataEvents := '';
  285. THackDataset(ds).DataEvent(deFieldChange,PtrInt(AFld));
  286. AssertEquals('deFieldChange:ID;',DataEvents);
  287. end;
  288. end;
  289. procedure TTestDatasources.TestDataEvent7;
  290. var aDatasource : TDataSource;
  291. aDatalink : TDataLink;
  292. ds : tdataset;
  293. AFld : TField;
  294. begin
  295. aDatasource := TDataSource.Create(nil);
  296. aDatalink := TTestDataLink.Create;
  297. aDatalink.DataSource := aDatasource;
  298. ds := DBConnector.GetTraceDataset(false);
  299. with ds do
  300. begin
  301. aDatasource.DataSet := ds;
  302. AFld := TIntegerField.Create(ds);
  303. AFld.FieldName := 'ID';
  304. AFld.DataSet := ds;
  305. AFld := TStringField.Create(ds);
  306. AFld.FieldName := 'NAME';
  307. AFld.DataSet := ds;
  308. AFld := TIntegerField.Create(ds);
  309. AFld.FieldName := 'CALCFLD';
  310. AFld.DataSet := ds;
  311. Afld.FieldKind := fkCalculated;
  312. // Ugly hack to imitate InternalCalcField, see
  313. // TDbfTraceDataset.InternalInitFieldDefs
  314. FieldDefs.Add('Name',ftString);
  315. FieldDefs.Find('Name').InternalCalcField:=True;
  316. open;
  317. AssertTrue(THackDataset(ds).InternalCalcFields);
  318. // If there are InternalCalcFields and 'normal' Calculated fields, only
  319. // RefreshIntenralCalcFields is called
  320. AFld := FieldByName('id');
  321. DataEvents := '';
  322. THackDataset(ds).DataEvent(deFieldChange,PtrInt(AFld));
  323. AssertEquals('RefreshInternalCalcFields;deFieldChange:ID;',DataEvents);
  324. AFld := FieldByName('name');
  325. AFld.FieldKind:=fkInternalCalc;
  326. DataEvents := '';
  327. THackDataset(ds).DataEvent(deFieldChange,PtrInt(AFld));
  328. AssertEquals('deFieldChange:NAME;',DataEvents);
  329. // If the TDataset.State is dsSetKey then IntenralCalcFields shoudn't get called
  330. THackDataset(ds).SetState(dsSetKey);
  331. AFld := FieldByName('id');
  332. DataEvents := '';
  333. THackDataset(ds).DataEvent(deFieldChange,PtrInt(AFld));
  334. AssertEquals('deFieldChange:ID;',DataEvents);
  335. end;
  336. end;
  337. procedure TTestDatasources.TestCalcFirstRecord1;
  338. var aDatasource : TDataSource;
  339. aDatalink : TDataLink;
  340. ds : tdataset;
  341. FirstRec : Integer;
  342. begin
  343. aDatasource := TDataSource.Create(nil);
  344. aDatalink := TTestDataLink.Create;
  345. aDatalink.DataSource := aDatasource;
  346. ds := DBConnector.GetNDataset(15);
  347. aDatasource.DataSet := ds;
  348. with ds do
  349. begin
  350. open;
  351. FirstRec := THackDataLink(aDatalink).FirstRecord;
  352. // Scroll '0' records, FirstRecord should stay the same,
  353. // and the there's no need to scroll the buffer.
  354. DataEvents := '';
  355. THackDataset(ds).DataEvent(deDataSetScroll,0);
  356. AssertEquals('deDataSetScroll:0;DataSetScrolled:0;',DataEvents);
  357. AssertEquals(FirstRec,THackDataLink(aDatalink).FirstRecord);
  358. // Scroll 1 record forward, FirstRecord should stay the same,
  359. // but the buffer is scrolled one place back.
  360. DataEvents := '';
  361. THackDataset(ds).DataEvent(deDataSetScroll,1);
  362. AssertEquals('deDataSetScroll:1;DataSetScrolled:-1;',DataEvents);
  363. AssertEquals(FirstRec,THackDataLink(aDatalink).FirstRecord);
  364. // Scroll 1 record backward, FirstRecord should stay the same,
  365. // but the buffer is scrolled one place back.
  366. DataEvents := '';
  367. THackDataset(ds).DataEvent(deDataSetScroll,-1);
  368. AssertEquals('deDataSetScroll:-1;DataSetScrolled:1;',DataEvents);
  369. AssertEquals(FirstRec,THackDataLink(aDatalink).FirstRecord);
  370. // Remove the datasource.
  371. aDatasource.DataSet := nil;
  372. DataEvents := '';
  373. THackDataset(ds).DataEvent(deDataSetScroll,1);
  374. AssertEquals('',DataEvents);
  375. // Set the buffer-size to 5 and add it to the dataset again
  376. aDatalink.BufferCount:=5;
  377. aDatasource.DataSet := ds;
  378. // Scroll '0' records, firstrecord should stay the same again,
  379. // and there's no need to scroll the buffer.
  380. DataEvents := '';
  381. THackDataset(ds).DataEvent(deDataSetScroll,0);
  382. AssertEquals('deDataSetScroll:0;DataSetScrolled:0;',DataEvents);
  383. AssertEquals(FirstRec,THackDataLink(aDatalink).FirstRecord);
  384. // Scroll 1 record backwards with a buffer size of 5.
  385. // Now the buffer won't scroll, but FirstRecord is decremented
  386. DataEvents := '';
  387. THackDataset(ds).DataEvent(deDataSetScroll,-1);
  388. AssertEquals('deDataSetScroll:-1;DataSetScrolled:0;',DataEvents);
  389. dec(FirstRec);
  390. AssertEquals(FirstRec,THackDataLink(aDatalink).FirstRecord);
  391. // Scroll one record forward again, no buffer scroll, FirstRecord
  392. // is inremented
  393. DataEvents := '';
  394. THackDataset(ds).DataEvent(deDataSetScroll,1);
  395. AssertEquals('deDataSetScroll:1;DataSetScrolled:0;',DataEvents);
  396. inc(FirstRec);
  397. AssertEquals(FirstRec,THackDataLink(aDatalink).FirstRecord);
  398. // Scroll one more record forward, buffer will scroll, FirstRecord
  399. // stays constant
  400. DataEvents := '';
  401. THackDataset(ds).DataEvent(deDataSetScroll,1);
  402. AssertEquals('deDataSetScroll:1;DataSetScrolled:-1;',DataEvents);
  403. AssertEquals(FirstRec,THackDataLink(aDatalink).FirstRecord);
  404. // Scroll two records backward, no buffer scroll, FirstRecord
  405. // is inremented twice
  406. DataEvents := '';
  407. THackDataset(ds).DataEvent(deDataSetScroll,-2);
  408. AssertEquals('deDataSetScroll:-2;DataSetScrolled:0;',DataEvents);
  409. dec(FirstRec,2);
  410. AssertEquals(FirstRec,THackDataLink(aDatalink).FirstRecord);
  411. // Scroll 6 records forward, so the buffer is scrolled 4 positions backward
  412. // and FirstRecord is Incremented by 2
  413. DataEvents := '';
  414. THackDataset(ds).DataEvent(deDataSetScroll,6);
  415. AssertEquals('deDataSetScroll:6;DataSetScrolled:-4;',DataEvents);
  416. inc(FirstRec,2);
  417. AssertEquals(FirstRec,THackDataLink(aDatalink).FirstRecord);
  418. // The other way around, scroll 6 records back, so the buffer is scrolled 2
  419. // positions forward and FirstRecord is decremented by 4
  420. DataEvents := '';
  421. THackDataset(ds).DataEvent(deDataSetScroll,-6);
  422. AssertEquals('deDataSetScroll:-6;DataSetScrolled:2;',DataEvents);
  423. dec(FirstRec,4);
  424. AssertEquals(FirstRec,THackDataLink(aDatalink).FirstRecord);
  425. end;
  426. end;
  427. procedure TTestDatasources.TestRefreshLookupList;
  428. var ds, lkpDs : TDataset;
  429. AFld1, AFld2, AFld3 : Tfield;
  430. Var1,Var2 : Variant;
  431. procedure TestLookupList;
  432. begin
  433. lkpDs.Open;
  434. lkpDs.first;
  435. while not LkpDs.eof do with AFld3 do
  436. begin
  437. Var1 := LkpDs.FieldValues[LookupResultField];
  438. Var2 := LookupList.ValueOfKey(LkpDs.fieldvalues[LookupKeyFields]);
  439. AssertEquals(VarToStr(Var1),VarToStr(Var2));
  440. lkpDs.Next;
  441. end;
  442. end;
  443. begin
  444. ds := DBConnector.GetNDataset(15);
  445. lkpDs := DBConnector.GetNDataset(5);
  446. with ds do
  447. begin
  448. AFld1 := TIntegerField.Create(ds);
  449. AFld1.FieldName := 'ID';
  450. AFld1.DataSet := ds;
  451. AFld2 := TStringField.Create(ds);
  452. AFld2.FieldName := 'NAME';
  453. AFld2.DataSet := ds;
  454. AFld3 := TIntegerField.Create(ds);
  455. with AFld3 do
  456. begin
  457. // Test if nothing happens when not all properties are filled
  458. FieldName := 'LookupFld';
  459. FieldKind := fkLookup;
  460. DataSet := ds;
  461. RefreshLookupList;
  462. LookupDataSet := lkpDs;
  463. RefreshLookupList;
  464. LookupKeyFields:='name';
  465. RefreshLookupList;
  466. LookupResultField:='ID';
  467. RefreshLookupList;
  468. KeyFields:='name';
  469. // Everything is filled in, this should run wihout any problems:
  470. RefreshLookupList;
  471. // The lookupdataset was closed, and should be closed again:
  472. AssertFalse(lkpDs.Active);
  473. // If some fields don't exist, check if an exception is raised:
  474. LookupKeyFields:='faulty';
  475. AssertException(EDatabaseError,RefreshLookupList);
  476. LookupKeyFields:='name';
  477. LookupResultField :='faulty';
  478. AssertException(EDatabaseError,RefreshLookupList);
  479. LookupResultField :='ID';
  480. // Check if the lookuplist is correctly filled
  481. RefreshLookupList;
  482. TestLookupList;
  483. // Check if the lookuplist is correctly filled when there are multiple
  484. // fields in the key
  485. LookupResultField:='name';
  486. LookupKeyFields:='id;name';
  487. RefreshLookupList;
  488. TestLookupList;
  489. end;
  490. AFld1.Free;
  491. AFld2.Free;
  492. AFld3.Free;
  493. end;
  494. end;
  495. procedure TTestDatasources.TestCalculateFields;
  496. var ds, lkpDs : TDataset;
  497. AFld1, AFld2, AFld3 : Tfield;
  498. StoreValue : Variant;
  499. Buffer: pchar;
  500. begin
  501. ds := DBConnector.GetTraceDataset(False);
  502. lkpDs := DBConnector.GetNDataset(5);
  503. with ds do
  504. begin
  505. AFld1 := TIntegerField.Create(ds);
  506. AFld1.FieldName := 'ID';
  507. AFld1.DataSet := ds;
  508. AFld2 := TStringField.Create(ds);
  509. AFld2.FieldName := 'NAME';
  510. AFld2.DataSet := ds;
  511. AFld3 := TIntegerField.Create(ds);
  512. with AFld3 do
  513. begin
  514. FieldName := 'LookupFld';
  515. FieldKind := fkLookup;
  516. DataSet := ds;
  517. LookupDataSet := lkpDs;
  518. LookupKeyFields:='name';
  519. LookupResultField:='ID';
  520. KeyFields := 'name';
  521. end;
  522. ds.OnCalcFields:=DatasetNotifyEvent;
  523. lkpds.Open;
  524. open;
  525. Buffer:=ds.ActiveBuffer;
  526. // If the state is dsInternalCalc, only the OnCalcField event should be called
  527. THackDataset(ds).SetState(dsInternalCalc);
  528. DataEvents:='';
  529. StoreValue:=AFld3.Value;
  530. THackDataset(ds).CalculateFields(Buffer);
  531. AssertEquals('CalculateFields;DatasetNotifyEvent;',DataEvents);
  532. AssertEquals(VarToStr(StoreValue),VarToSTr(AFld3.Value));
  533. THackDataset(ds).SetState(dsBrowse);
  534. // Also if the dataset is Unidirectional, only the OnCalcField event should be called
  535. THackDataset(ds).SetUniDirectional(True);
  536. DataEvents:='';
  537. StoreValue:=AFld3.Value;
  538. THackDataset(ds).CalculateFields(Buffer);
  539. AssertEquals('CalculateFields;DatasetNotifyEvent;',DataEvents);
  540. AssertEquals(VarToStr(StoreValue),VarToSTr(AFld3.Value));
  541. THackDataset(ds).SetUniDirectional(False);
  542. // Else, the value of all the lookup fields should get calculated
  543. DataEvents:='';
  544. THackDataset(ds).CalculateFields(Buffer);
  545. AssertEquals('CalculateFields;ClearCalcFields;DatasetNotifyEvent;',DataEvents);
  546. // This assertion fails because of bug 11027
  547. //AssertEquals('1',VarToStr(StoreValue));
  548. end;
  549. end;
  550. initialization
  551. if uppercase(dbconnectorname)='DBF' then RegisterTest(TTestDatasources);
  552. end.