@@ -37,6 +37,141 @@ class StorageAggregateFunctionsTests: XCTestCase {
3737 self . apiProvider = nil
3838 }
3939
40+ func testMin( ) throws {
41+ try testCase ( #function, routine: {
42+ struct MinTest {
43+ var value : Int = 0
44+ var nullableValue : Int ? = 0
45+ var unknown = 0
46+ }
47+ let apiProvider = SQLiteApiProviderMock ( )
48+ apiProvider. forwardsCalls = true
49+ let storage = try Storage ( filename: " " ,
50+ apiProvider: apiProvider,
51+ tables: [ Table < MinTest > ( name: " min_test " ,
52+ columns:
53+ Column ( name: " value " , keyPath: \MinTest . value) ,
54+ Column ( name: " null_value " , keyPath: \MinTest . nullableValue) ) ] )
55+ try storage. syncSchema ( preserve: false )
56+ try section ( " error " , routine: {
57+ try section ( " error notMappedType " , routine: {
58+ do {
59+ _ = try storage. max ( \Unknown . value)
60+ XCTAssert ( false )
61+ } catch SQLiteORM . Error . typeIsNotMapped{
62+ XCTAssert ( true )
63+ } catch {
64+ XCTAssert ( false )
65+ }
66+ } )
67+ try section ( " error columnNotFound " , routine: {
68+ do {
69+ _ = try storage. max ( \MinTest . unknown)
70+ XCTAssert ( false )
71+ } catch SQLiteORM . Error . columnNotFound{
72+ XCTAssert ( true )
73+ } catch {
74+ XCTAssert ( false )
75+ }
76+ } )
77+ } )
78+ try section ( " no error " , routine: {
79+ let db = storage. connection. dbMaybe!
80+ var expectedResult : Int ?
81+ var result : Int ?
82+ var expectedApiCalls = [ SQLiteApiProviderMock . Call] ( )
83+ try section ( " not nullable field " , routine: {
84+ try section ( " no rows " , routine: {
85+ expectedResult = nil
86+ expectedApiCalls = [
87+ . init( id: 0 , callType: . sqlite3PrepareV2( db, " SELECT MIN(value) FROM min_test " , - 1 , . ignore, nil ) ) ,
88+ . init( id: 1 , callType: . sqlite3Step( . ignore) ) ,
89+ . init( id: 2 , callType: . sqlite3ColumnValue( . ignore, 0 ) ) ,
90+ . init( id: 3 , callType: . sqlite3ValueType( . ignore) ) ,
91+ . init( id: 4 , callType: . sqlite3Step( . ignore) ) ,
92+ . init( id: 5 , callType: . sqlite3Finalize( . ignore) ) ,
93+ ]
94+ } )
95+ try section ( " 1 row " , routine: {
96+ try storage. replace ( object: MinTest ( value: 10 ) )
97+ expectedResult = 10
98+ expectedApiCalls = [
99+ . init( id: 0 , callType: . sqlite3PrepareV2( db, " SELECT MIN(value) FROM min_test " , - 1 , . ignore, nil ) ) ,
100+ . init( id: 1 , callType: . sqlite3Step( . ignore) ) ,
101+ . init( id: 2 , callType: . sqlite3ColumnValue( . ignore, 0 ) ) ,
102+ . init( id: 3 , callType: . sqlite3ValueType( . ignore) ) ,
103+ . init( id: 4 , callType: . sqlite3ValueInt( . ignore) ) ,
104+ . init( id: 5 , callType: . sqlite3Step( . ignore) ) ,
105+ . init( id: 6 , callType: . sqlite3Finalize( . ignore) ) ,
106+ ]
107+ } )
108+ try section ( " 2 rows " , routine: {
109+ try storage. replace ( object: MinTest ( value: 4 ) )
110+ try storage. replace ( object: MinTest ( value: 6 ) )
111+ expectedResult = 4
112+ expectedApiCalls = [
113+ . init( id: 0 , callType: . sqlite3PrepareV2( db, " SELECT MIN(value) FROM min_test " , - 1 , . ignore, nil ) ) ,
114+ . init( id: 1 , callType: . sqlite3Step( . ignore) ) ,
115+ . init( id: 2 , callType: . sqlite3ColumnValue( . ignore, 0 ) ) ,
116+ . init( id: 3 , callType: . sqlite3ValueType( . ignore) ) ,
117+ . init( id: 4 , callType: . sqlite3ValueInt( . ignore) ) ,
118+ . init( id: 5 , callType: . sqlite3Step( . ignore) ) ,
119+ . init( id: 6 , callType: . sqlite3Finalize( . ignore) ) ,
120+ ]
121+ } )
122+ apiProvider. resetCalls ( )
123+ result = try storage. min ( \MinTest . value)
124+ XCTAssertEqual ( result, expectedResult)
125+ XCTAssertEqual ( apiProvider. calls, expectedApiCalls)
126+ } )
127+ try section ( " nullable field " , routine: {
128+ try section ( " no rows " , routine: {
129+ expectedResult = nil
130+ expectedApiCalls = [
131+ . init( id: 0 , callType: . sqlite3PrepareV2( db, " SELECT MIN(null_value) FROM min_test " , - 1 , . ignore, nil ) ) ,
132+ . init( id: 1 , callType: . sqlite3Step( . ignore) ) ,
133+ . init( id: 2 , callType: . sqlite3ColumnValue( . ignore, 0 ) ) ,
134+ . init( id: 3 , callType: . sqlite3ValueType( . ignore) ) ,
135+ . init( id: 4 , callType: . sqlite3Step( . ignore) ) ,
136+ . init( id: 5 , callType: . sqlite3Finalize( . ignore) ) ,
137+ ]
138+ } )
139+ try section ( " 1 row " , routine: {
140+ try storage. replace ( object: MinTest ( value: 0 , nullableValue: 10 ) )
141+ expectedResult = 10
142+ expectedApiCalls = [
143+ . init( id: 0 , callType: . sqlite3PrepareV2( db, " SELECT MIN(null_value) FROM min_test " , - 1 , . ignore, nil ) ) ,
144+ . init( id: 1 , callType: . sqlite3Step( . ignore) ) ,
145+ . init( id: 2 , callType: . sqlite3ColumnValue( . ignore, 0 ) ) ,
146+ . init( id: 3 , callType: . sqlite3ValueType( . ignore) ) ,
147+ . init( id: 4 , callType: . sqlite3ValueInt( . ignore) ) ,
148+ . init( id: 5 , callType: . sqlite3Step( . ignore) ) ,
149+ . init( id: 6 , callType: . sqlite3Finalize( . ignore) ) ,
150+ ]
151+ } )
152+ try section ( " 2 rows " , routine: {
153+ try storage. replace ( object: MinTest ( value: 0 , nullableValue: 4 ) )
154+ try storage. replace ( object: MinTest ( value: 0 , nullableValue: 6 ) )
155+ expectedResult = 4
156+ expectedApiCalls = [
157+ . init( id: 0 , callType: . sqlite3PrepareV2( db, " SELECT MIN(null_value) FROM min_test " , - 1 , . ignore, nil ) ) ,
158+ . init( id: 1 , callType: . sqlite3Step( . ignore) ) ,
159+ . init( id: 2 , callType: . sqlite3ColumnValue( . ignore, 0 ) ) ,
160+ . init( id: 3 , callType: . sqlite3ValueType( . ignore) ) ,
161+ . init( id: 4 , callType: . sqlite3ValueInt( . ignore) ) ,
162+ . init( id: 5 , callType: . sqlite3Step( . ignore) ) ,
163+ . init( id: 6 , callType: . sqlite3Finalize( . ignore) ) ,
164+ ]
165+ } )
166+ apiProvider. resetCalls ( )
167+ result = try storage. min ( \MinTest . nullableValue)
168+ XCTAssertEqual ( result, expectedResult)
169+ XCTAssertEqual ( apiProvider. calls, expectedApiCalls)
170+ } )
171+ } )
172+ } )
173+ }
174+
40175 func testMax( ) throws {
41176 try testCase ( #function, routine: {
42177 struct MaxTest {
0 commit comments