@@ -6,6 +6,131 @@ class StorageAggregateFunctionsTests: XCTestCase {
66 var value = Double ( 0 )
77 } ;
88
9+ func testTotal( ) throws {
10+ try testCase ( #function, routine: {
11+ struct TotalTest {
12+ var value : Int = 0
13+ var nullableValue : Int ? = 0
14+ var unknown = 0
15+ }
16+ let apiProvider = SQLiteApiProviderMock ( )
17+ apiProvider. forwardsCalls = true
18+ let storage = try Storage ( filename: " " ,
19+ apiProvider: apiProvider,
20+ tables: [ Table < TotalTest > ( name: " total_test " ,
21+ columns:
22+ Column ( name: " value " , keyPath: \TotalTest . value) ,
23+ Column ( name: " null_value " , keyPath: \TotalTest . nullableValue) ) ] )
24+ try storage. syncSchema ( preserve: false )
25+ try section ( " error " , routine: {
26+ try section ( " error notMappedType " , routine: {
27+ do {
28+ _ = try storage. total ( \Unknown . value)
29+ XCTAssert ( false )
30+ } catch SQLiteORM . Error . typeIsNotMapped{
31+ XCTAssert ( true )
32+ } catch {
33+ XCTAssert ( false )
34+ }
35+ } )
36+ try section ( " error columnNotFound " , routine: {
37+ do {
38+ _ = try storage. total ( \TotalTest . unknown)
39+ XCTAssert ( false )
40+ } catch SQLiteORM . Error . columnNotFound{
41+ XCTAssert ( true )
42+ } catch {
43+ XCTAssert ( false )
44+ }
45+ } )
46+ } )
47+ try section ( " no error " , routine: {
48+ let db = storage. connection. dbMaybe!
49+ var expectedResult : Double = 0
50+ var result : Double = - 1
51+ var expectedApiCalls = [ SQLiteApiProviderMock . Call] ( )
52+ try section ( " not nullable field " , routine: {
53+ try section ( " no rows " , routine: {
54+ expectedResult = 0
55+ expectedApiCalls = [
56+ . init( id: 0 , callType: . sqlite3PrepareV2( db, " SELECT TOTAL(value) FROM total_test " , - 1 , . ignore, nil ) ) ,
57+ . init( id: 1 , callType: . sqlite3Step( . ignore) ) ,
58+ . init( id: 2 , callType: . sqlite3ColumnDouble( . ignore, 0 ) ) ,
59+ . init( id: 3 , callType: . sqlite3Step( . ignore) ) ,
60+ . init( id: 4 , callType: . sqlite3Finalize( . ignore) ) ,
61+ ]
62+ } )
63+ try section ( " 1 row " , routine: {
64+ try storage. replace ( object: TotalTest ( value: 1 ) )
65+ expectedResult = 1
66+ expectedApiCalls = [
67+ . init( id: 0 , callType: . sqlite3PrepareV2( db, " SELECT TOTAL(value) FROM total_test " , - 1 , . ignore, nil ) ) ,
68+ . init( id: 1 , callType: . sqlite3Step( . ignore) ) ,
69+ . init( id: 2 , callType: . sqlite3ColumnDouble( . ignore, 0 ) ) ,
70+ . init( id: 3 , callType: . sqlite3Step( . ignore) ) ,
71+ . init( id: 4 , callType: . sqlite3Finalize( . ignore) ) ,
72+ ]
73+ } )
74+ try section ( " 2 rows " , routine: {
75+ try storage. replace ( object: TotalTest ( value: 2 ) )
76+ try storage. replace ( object: TotalTest ( value: 3 ) )
77+ expectedResult = 5
78+ expectedApiCalls = [
79+ . init( id: 0 , callType: . sqlite3PrepareV2( db, " SELECT TOTAL(value) FROM total_test " , - 1 , . ignore, nil ) ) ,
80+ . init( id: 1 , callType: . sqlite3Step( . ignore) ) ,
81+ . init( id: 2 , callType: . sqlite3ColumnDouble( . ignore, 0 ) ) ,
82+ . init( id: 3 , callType: . sqlite3Step( . ignore) ) ,
83+ . init( id: 4 , callType: . sqlite3Finalize( . ignore) ) ,
84+ ]
85+ } )
86+ apiProvider. resetCalls ( )
87+ result = try storage. total ( \TotalTest . value)
88+ XCTAssertEqual ( result, expectedResult)
89+ XCTAssertEqual ( apiProvider. calls, expectedApiCalls)
90+ } )
91+ try section ( " nullable field " , routine: {
92+ try section ( " no rows " , routine: {
93+ expectedResult = 0
94+ expectedApiCalls = [
95+ . init( id: 0 , callType: . sqlite3PrepareV2( db, " SELECT TOTAL(null_value) FROM total_test " , - 1 , . ignore, nil ) ) ,
96+ . init( id: 1 , callType: . sqlite3Step( . ignore) ) ,
97+ . init( id: 2 , callType: . sqlite3ColumnDouble( . ignore, 0 ) ) ,
98+ . init( id: 3 , callType: . sqlite3Step( . ignore) ) ,
99+ . init( id: 4 , callType: . sqlite3Finalize( . ignore) ) ,
100+ ]
101+ } )
102+ try section ( " 1 row " , routine: {
103+ try storage. replace ( object: TotalTest ( value: 0 , nullableValue: 3 ) )
104+ expectedResult = 3
105+ expectedApiCalls = [
106+ . init( id: 0 , callType: . sqlite3PrepareV2( db, " SELECT TOTAL(null_value) FROM total_test " , - 1 , . ignore, nil ) ) ,
107+ . init( id: 1 , callType: . sqlite3Step( . ignore) ) ,
108+ . init( id: 2 , callType: . sqlite3ColumnDouble( . ignore, 0 ) ) ,
109+ . init( id: 3 , callType: . sqlite3Step( . ignore) ) ,
110+ . init( id: 4 , callType: . sqlite3Finalize( . ignore) ) ,
111+ ]
112+ } )
113+ try section ( " 2 rows " , routine: {
114+ try storage. replace ( object: TotalTest ( value: 0 , nullableValue: 4 ) )
115+ try storage. replace ( object: TotalTest ( value: 0 , nullableValue: 6 ) )
116+ expectedResult = 10
117+ expectedApiCalls = [
118+ . init( id: 0 , callType: . sqlite3PrepareV2( db, " SELECT TOTAL(null_value) FROM total_test " , - 1 , . ignore, nil ) ) ,
119+ . init( id: 1 , callType: . sqlite3Step( . ignore) ) ,
120+ . init( id: 2 , callType: . sqlite3ColumnDouble( . ignore, 0 ) ) ,
121+ . init( id: 3 , callType: . sqlite3Step( . ignore) ) ,
122+ . init( id: 4 , callType: . sqlite3Finalize( . ignore) ) ,
123+ ]
124+ } )
125+ apiProvider. resetCalls ( )
126+ result = try storage. total ( \TotalTest . nullableValue)
127+ XCTAssertEqual ( result, expectedResult)
128+ XCTAssertEqual ( apiProvider. calls, expectedApiCalls)
129+ } )
130+ } )
131+ } )
132+ }
133+
9134 func testSum( ) throws {
10135 try testCase ( #function, routine: {
11136 struct SumTest {
0 commit comments