Golang: optimal variant run tests in transaction - unit-testing

Creating tests for database models.
My goal test all testCases in transactions.
Uses "github.com/stretchr/testify/suite"
Closure use to create records in transaction.
What do you think about this approach?
This code works, but I think: may be there is a more efficient way.
May be I should use another approach, advise me please.
I am a newbie in golang )
type tcCreateAccount struct {
name string
errMsg string
closure func(p *CreateAccountParams, q *Queries)
params CreateAccountParams
}
func (tc *tcCreateAccount) setup(s *accountTestSuiteType, q *Queries) {
user := createRandomUser(s.T(), s.ctx, q)
exchange := createRandomExchange(s.T(), s.ctx, q)
name := fmt.Sprintf("%s account at %s exchange", user.FullName, exchange.Name)
tc.params.OwnerID = user.UserID
tc.params.ExchangeID = exchange.ExchangeID
tc.params.Name = name
}
type closureType func(p *CreateAccountParams, q *Queries)
func newCreateAccountTestCase(name, errMsg string, closures ...closureType) tcCreateAccount {
var closure closureType
if len(closures) > 0 {
closure = closures[0]
}
return tcCreateAccount{
name: name,
errMsg: errMsg,
params: CreateAccountParams{
ApiKey: gofakeit.BitcoinPrivateKey(),
ApiSecret: gofakeit.BitcoinPrivateKey(),
Passphrase: gofakeit.Password(true, true, true, true, true, 12),
},
closure: closure,
}
}
func (s *accountTestSuiteType) TestCreateAccount() {
testCases := make([]tcCreateAccount, 0, 20)
testCases = append(testCases, newCreateAccountTestCase("Create regular accout", ""))
testCases = append(testCases,
newCreateAccountTestCase(`Create accout without ApiKey`, ``, func(p *CreateAccountParams, q *Queries) {
p.ApiKey = ``
}))
testCases = append(testCases,
newCreateAccountTestCase(`Create accout without ApiSecret`, ``, func(p *CreateAccountParams, q *Queries) {
p.ApiSecret = ``
}))
testCases = append(testCases,
newCreateAccountTestCase(`Create accout without Passphrase`, ``, func(p *CreateAccountParams, q *Queries) {
p.Passphrase = ``
}))
testCases = append(testCases,
newCreateAccountTestCase(`Create accout without OwnerID`, `"account_owner_id" (SQLSTATE 23514)`,
func(p *CreateAccountParams, q *Queries) {
p.OwnerID = 0
}))
testCases = append(testCases,
newCreateAccountTestCase(`Create accout without ExchangeID`, `"account_exchange_id" (SQLSTATE 23514)`,
func(p *CreateAccountParams, q *Queries) {
p.ExchangeID = 0
}))
testCases = append(testCases,
newCreateAccountTestCase(`Create accout without Name`, `"account_name_length" (SQLSTATE 23514)`,
func(p *CreateAccountParams, q *Queries) {
p.Name = ``
}))
testCases = append(testCases,
newCreateAccountTestCase(`Create not unique account`, `"accounts_name_owner_id_exchange_id_idx" (SQLSTATE 23505)`,
func(p *CreateAccountParams, q *Queries) {
a := createRandomAccount(s.T(), s.ctx, q)
p.ExchangeID = a.ExchangeID
p.OwnerID = a.OwnerID
p.Name = a.Name
}))
testCases = append(testCases,
newCreateAccountTestCase(`Create accout with random OwnerID`, `"accounts_owner_id_fkey" (SQLSTATE 23503)`,
func(p *CreateAccountParams, q *Queries) {
p.OwnerID = randomID()
}))
testCases = append(testCases,
newCreateAccountTestCase(`Create accout with random ExchangeID`, `"accounts_exchange_id_fkey" (SQLSTATE 23503)`,
func(p *CreateAccountParams, q *Queries) {
p.ExchangeID = randomID()
}))
for _, tc := range testCases {
err := s.store.ExecTx(s.ctx, func(q *Queries) error {
tc.setup(s, q)
if tc.closure != nil {
tc.closure(&tc.params, q)
}
account, err := q.CreateAccount(s.ctx, tc.params)
if len(tc.errMsg) == 0 {
s.T().Logf("Success case: %s", tc.name)
s.Require().NoError(err)
s.Require().NotEmpty(account)
s.Require().Equal(tc.params.OwnerID, account.OwnerID)
s.Require().Equal(tc.params.ExchangeID, account.ExchangeID)
s.Require().Equal(tc.params.Name, account.Name)
s.Require().Equal(tc.params.ApiKey, account.ApiKey)
s.Require().Equal(tc.params.ApiSecret, account.ApiSecret)
s.Require().Equal(tc.params.Passphrase, account.Passphrase)
} else {
s.T().Logf("Fail case: %s", tc.name)
s.Require().Error(err)
s.Require().Empty(account)
s.Require().ErrorContains(err, tc.errMsg)
}
return errRollbackTX
})
s.Require().ErrorIs(err, errRollbackTX)
}
}```

Related

Putting children in one list

Please tell me how in such a data structure (simplified for better understanding) to bring all the children of the entity into one list:
fun main() {
val listOfEntities = listOf(
Entity(
name = "John",
entities = listOf(
Entity(
name = "Adam",
entities = listOf()
),
Entity(
name = "Ivan",
entities = listOf(
Entity(
name = "Henry",
entities = listOf(
Entity(
name = "Kate",
entities = listOf(
Entity(
name = "Bob",
entities = listOf()
)
)
)
)
)
)
)
)
)
)
val result = listOfEntities.flatMap { it.entities }.map { it.name }
println(result)
}
data class Entity(
val name: String,
val entities: List<Entity>
)
I expect to see following result:
[John, Adam, Ivan, Henry, Kate, Bob]
I try to use flatMap, but it did not lead to the expected result.
Thank you in advance!
You can traverse the tree of Entities recursively like this:
fun List<Entity>.flattenEntities(): List<Entity> =
this + flatMap { it.entities.flattenEntities() }
Then you can call
val result = listOfEntities.flattenEntities().map { it.name }
to obtain the desired result.
You could do it like this
fun List<Entity>.flatten(): List<String> {
return flatMap { listOf(it.name) + it.entities.flatten()}
}
and then
val result = listOfEntities.flatten()

Swift5 SwiftUI conforming to to Hashable causes undeclared type

I am trying to make a class "Activity" as hashable for use in swiftUI List. I followed protocol instructions for making it hashable, but when I do,I get an error later in the code that says I am using an undeclared type. This type is valid (in firebase import) if I do not try to make the class hashable. I am running XCode 11.3.1 and Swift 5.
I was hoping someone could lend an eye and help me figure this out.
The updates to the code I use to make it hashable is below:
class Activity: Identifiable, Hashable {
func hash(into hasher: inout Hasher) {
hasher.combine(id)
}
static func == (lhs: Activity, rhs: Activity) -> Bool {
return lhs.id == rhs.id
}
But when I do this, I get the following error later in the code which appears completely unrelated.
init(document: DocumentSnapshot) {
self.id = document.documentID
---> Use of undeclared type 'DocumentSnapshot'
When I do not add that code, I do not get that error. Clearly I am doing something stupid.
Here is the entire class (before hashable) with no errors:
import Foundation
import Firebase
class Activity: Identifiable {
var id: String?
var activityDateTime: Date
var activityName: String
var activityType: String
var displayName: String
var distance: Double
var distanceUnits: String
var duration: Double
var email: String
var teamName: String
var teamUid: String
var uid: String
init() {
self.id = nil
self.activityDateTime = Date()
self.activityName = ""
self.activityType = ""
self.displayName = ""
self.distance = 0.0
self.distanceUnits = ""
self.duration = 0.0
self.email = ""
self.teamName = ""
self.teamUid = ""
self.uid = ""
}
init(id: String, activityName: String, distance: Double) {
self.id = id
self.activityDateTime = Date()
self.activityName = activityName
self.activityType = ""
self.displayName = ""
self.distance = distance
self.distanceUnits = "Miles"
self.duration = 0.0
self.email = ""
self.teamName = ""
self.teamUid = ""
self.uid = ""
}
init(document: DocumentSnapshot) {
self.id = document.documentID
let timestamp = document.get("activityDateTime") as! Timestamp
self.activityDateTime = timestamp.dateValue()
self.activityName = document.get("activityName") as? String ?? ""
self.activityType = document.get("activityType") as? String ?? ""
self.displayName = document.get("displayName") as? String ?? ""
self.distance = document.get("distance") as? Double ?? 0.0
self.distanceUnits = document.get("distanceUnits") as? String ?? "Miles"
self.duration = document.get("duration") as? Double ?? 0.0
self.email = document.get("email") as? String ?? ""
self.teamName = document.get("teamName") as? String ?? ""
self.teamUid = document.get("teamUid") as? String ?? ""
self.uid = document.get("uid") as? String ?? ""
}
// For JSON Output
func toAnyObject() -> Any {
return [
"id": id as Any,
"activityDateTime": activityDateTime,
"activityName": activityName,
"activityType": activityType,
"displayName": displayName,
"distance": distance,
"distanceUnits": distanceUnits,
"duration": duration,
"email": email,
"teamName": teamName,
"teamUid": teamName,
"uid": uid
]
}
}
And here is the full class with hashable that causes the error to occur
import Foundation
import Firebase
class Activity: Identifiable, Hashable {
func hash(into hasher: inout Hasher) {
hasher.combine(id)
}
static func == (lhs: Activity, rhs: Activity) -> Bool {
return lhs.id == rhs.id
}
var id: String?
var activityDateTime: Date
var activityName: String
var activityType: String
var displayName: String
var distance: Double
var distanceUnits: String
var duration: Double
var email: String
var teamName: String
var teamUid: String
var uid: String
init() {
self.id = nil
self.activityDateTime = Date()
self.activityName = ""
self.activityType = ""
self.displayName = ""
self.distance = 0.0
self.distanceUnits = ""
self.duration = 0.0
self.email = ""
self.teamName = ""
self.teamUid = ""
self.uid = ""
}
init(id: String, activityName: String, distance: Double) {
self.id = id
self.activityDateTime = Date()
self.activityName = activityName
self.activityType = ""
self.displayName = ""
self.distance = distance
self.distanceUnits = "Miles"
self.duration = 0.0
self.email = ""
self.teamName = ""
self.teamUid = ""
self.uid = ""
}
init(document: DocumentSnapshot) {
self.id = document.documentID
let timestamp = document.get("activityDateTime") as! Timestamp
self.activityDateTime = timestamp.dateValue()
self.activityName = document.get("activityName") as? String ?? ""
self.activityType = document.get("activityType") as? String ?? ""
self.displayName = document.get("displayName") as? String ?? ""
self.distance = document.get("distance") as? Double ?? 0.0
self.distanceUnits = document.get("distanceUnits") as? String ?? "Miles"
self.duration = document.get("duration") as? Double ?? 0.0
self.email = document.get("email") as? String ?? ""
self.teamName = document.get("teamName") as? String ?? ""
self.teamUid = document.get("teamUid") as? String ?? ""
self.uid = document.get("uid") as? String ?? ""
}
// For JSON Output
func toAnyObject() -> Any {
return [
"id": id as Any,
"activityDateTime": activityDateTime,
"activityName": activityName,
"activityType": activityType,
"displayName": displayName,
"distance": distance,
"distanceUnits": distanceUnits,
"duration": duration,
"email": email,
"teamName": teamName,
"teamUid": teamName,
"uid": uid
]
}
}

Last column data overwritten all the column while inserting

I having this problem when I inserting data row and the result comes out 'SUCCESS'. But when I print out the table, something like below came out. I have been trying on this for days but couldn't figure out where whet wrong.
Logs:
Successfully inserted row. >> aaa sss ddd fff
Successfully inserted row. >> zzz xxx ccc vvv
Successfully inserted row. >> 9999999 00000000 aaaaaaa bbbbbbbbbbbbb
Successfully inserted row. >> ccccccccccccc ddddddddddd eeeeeeeeeeee fffffffffffffffff
Successfully inserted row. >> gggggggggggg hhhhhhhhhhhh iiiiiiiiiiiii jjjjjjjjjjjjjj
Successfully inserted row. >> kkkkkkkkkkk LLLLLLLLLL mmmmmmmm nnnnnnnnnnnnn
Query Result= id:1 msgID:fff loginID:fff conversationID:fff userID:fff
Query Result= id:2 msgID:vvv loginID:vvv conversationID:vvv userID:vvv
Query Result= id:3 msgID:bbbbbbb loginID:bbbbbbb conversationID:bbbbbbbb userID:bbbbbbbbbbbbb
Query Result= id:4 msgID:ddddddddddd loginID:ddddddddddd conversationID:ddddddddddd userID:fffffffffffffffff
Query Result= id:5 msgID:jjjjjjjjjjjjj loginID:jjjjjjjjjjjj conversationID:jjjjjjjjjjjj userID:jjjjjjjjjjjjjj
Query Result= id:6 msgID:nnnnnnnn loginID:nnnnnnnnnnn conversationID:nnnnnnnnnn userID:nnnnnnnnnnnnn
I'm sure the database connection is fine, but it just came out wrong. I even checked if my parameters are input correctly.
When I call my function:
DB_Handler.add_msgstatus(loginID: "aaa", conversationID: "sss", msgID: "ddd", userID: "fff")
DB_Handler.add_msgstatus(loginID: "zzz", conversationID: "xxx", msgID: "ccc", userID: "vvv")
DB_Handler.add_msgstatus(loginID: "9999999", conversationID: "00000000", msgID: "aaaaaaa", userID: "bbbbbbbbbbbbb")
DB_Handler.add_msgstatus(loginID: "ccccccccccccc", conversationID: "ddddddddddd", msgID: "eeeeeeeeeeee", userID: "fffffffffffffffff")
DB_Handler.add_msgstatus(loginID: "gggggggggggg", conversationID: "hhhhhhhhhhhh", msgID: "iiiiiiiiiiiii", userID: "jjjjjjjjjjjjjj")
DB_Handler.add_msgstatus(loginID: "kkkkkkkkkkk", conversationID: "LLLLLLLLLL", msgID: "mmmmmmmm", userID: "nnnnnnnnnnnnn")
DB_Handler.getAllMsgStatusInfo()
My insert row function:
static func add_msgstatus(loginID: String, conversationID: String, msgID: String, userID: String) {
let queryString = "INSERT INTO msgstatus_tbl (id, msg_id, login_id, conversation_id, user_id) VALUES (null, ?, ?, ?, ?);"
var preparedStmt: OpaquePointer? = nil
if sqlite3_prepare(db, queryString, -1, &preparedStmt, nil) == SQLITE_OK {
sqlite3_bind_text(preparedStmt, 1, msgID, -1, nil)
sqlite3_bind_text(preparedStmt, 2, loginID, -1, nil)
sqlite3_bind_text(preparedStmt, 3, conversationID, -1, nil)
sqlite3_bind_text(preparedStmt, 4, userID, -1, nil)
if sqlite3_step(preparedStmt) == SQLITE_DONE {
print("Successfully inserted row. >> \(loginID) \(conversationID) \(msgID) \(userID)")
} else {
let errorMessage = String.init(cString: sqlite3_errmsg(db))
print("Fail to insert row. \(errorMessage)")
}
sqlite3_finalize(preparedStmt)
} else {
let errorMessage = String.init(cString: sqlite3_errmsg(db))
print("Unable to prepare statement. \(errorMessage)")
}
}
My table:
static func create_msgstatus_tbl() {
let queryString = "CREATE TABLE IF NOT EXISTS msgstatus_tbl (id INTEGER PRIMARY KEY, msg_id VARCHAR(255), login_id VARCHAR(255), conversation_id VARCHAR(255), user_id VARCHAR(255));"
var preparedStmt: OpaquePointer? = nil
if sqlite3_prepare_v2(db, queryString, -1, &preparedStmt, nil) == SQLITE_OK {
if sqlite3_step(preparedStmt) == SQLITE_DONE {
print("Table (msgstatus_tbl) exists/ created.")
} else {
print("Table (msgstatus_tbl) could not be created.")
}
sqlite3_finalize(preparedStmt)
} else {
let errorMessage = String.init(cString: sqlite3_errmsg(db))
print("Unable to prepare statement. \(errorMessage)")
}
}
My retrieve data function:
static func getAllMsgStatusInfo() {
let queryString = "SELECT * FROM msgstatus_tbl;"
var preparedStmt: OpaquePointer? = nil
if sqlite3_prepare_v2(db, queryString, -1, &preparedStmt, nil) == SQLITE_OK {
var msgID = ""
var loginID = ""
var conversationID = ""
var userID = ""
var id = ""
while (sqlite3_step(preparedStmt) == SQLITE_ROW) {
id = String(cString: sqlite3_column_text(preparedStmt, 0))
msgID = String(cString: sqlite3_column_text(preparedStmt, 1))
loginID = String(cString: sqlite3_column_text(preparedStmt, 2))
conversationID = String(cString: sqlite3_column_text(preparedStmt, 3))
userID = String(cString: sqlite3_column_text(preparedStmt, 4))
print("Query Result= id:\(id) msgID:\(msgID) loginID:\(loginID) conversationID:\(conversationID) userID:\(userID)")
}
sqlite3_finalize(preparedStmt)
} else {
let errorMessage = String.init(cString: sqlite3_errmsg(db))
print("Unable to prepare statement. \(errorMessage)")
}
}
You need to do one thing.
When you use sqlite3_bind_text(preparedStmt, 1, msgID, -1, nil) then just follow these following steps -:
let msgId = msgID as NSString
sqlite3_bind_text(preparedStmt, 1, msgId.utf8String, -1, nil)
Do these same things for all your next sqlite3_bind_text statement as mentioned in your code.
I also faced same problem like you. And it is working now for me. I hope it will work for you.

How to make a combined chart of "line chart" and "bar chart"?

i found methods for swift2 but couldn't make a swift3 one. Can anybody help me making swift3 code of these combined chart?
I found these codes:
months = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]
unitsSold = [20.0, 4.0, 6.0,20.0, 4.0, 6.0,20.0, 4.0, 6.0,20.0, 4.0, 6.0]
databozi = [10.0, 11.0, 12.0,10.0, 11.0, 12.0,10.0, 11.0, 12.0,10.0, 11.0, 12.0]
func convertCombines(dataEntryX forX:[String],dataEntryY forY: [Double], dataEntryZ forZ: [Double]) {
var dataEntries = [BarChartDataEntry]()
var dataEntrieszor = [ChartDataEntry]()
for i in 0..<forX.count {
dataEntries.append(BarChartDataEntry(x: forZ[i], y: Double(i)))
dataEntrieszor.append(ChartDataEntry(x: forY[i], y: Double(i)))
}
let lineChartSet = LineChartDataSet(values: dataEntrieszor, label: "Line Data")
let lineChartData = LineChartData(dataSets: [lineChartSet])
let barChartSet = BarChartDataSet(values: dataEntries, label: "Bar Data")
let barChartData = BarChartData(dataSets: [barChartSet])
//ui
lineChartSet.setColor(UIColor.red)
lineChartSet.setCircleColor(UIColor.red)
let comData = CombinedChartData(dataSets: [lineChartSet,barChartSet])
comData.barData = barChartData
comData.lineData = lineChartData
combinedChartViewOut.data = comData
combinedChartViewOut.notifyDataSetChanged()
}
my Example code pic
my Example code pic
but
need code like :
Example Combined pic
fix code :
func convertCombines(dataEntryX forX:[String],dataEntryY forY: [Double], dataEntryZ forZ: [Double]) {
var dataEntries: [BarChartDataEntry] = []
var dataEntrieszor: [ChartDataEntry] = [ChartDataEntry]()
for (i, v) in forY.enumerated() {
let dataEntry = ChartDataEntry(x: Double(i), y: v, data: forX as AnyObject?)
dataEntrieszor.append(dataEntry)
}
for (i, v) in forZ.enumerated() {
let dataEntry = BarChartDataEntry(x: Double(i), y: v, data: forX as AnyObject?)
dataEntries.append(dataEntry)
}
let lineChartSet = LineChartDataSet(values: dataEntrieszor, label: "Line Data")
let lineChartData = LineChartData(dataSets: [lineChartSet])
let barChartSet = BarChartDataSet(values: dataEntries, label: "Bar Data")
let barChartData = BarChartData(dataSets: [barChartSet])
//ui
lineChartSet.setColor(UIColor.red)
lineChartSet.setCircleColor(UIColor.red)
let comData = CombinedChartData(dataSets: [lineChartSet,barChartSet])
comData.barData = barChartData
comData.lineData = lineChartData
combinedChartViewOut.data = comData
combinedChartViewOut.notifyDataSetChanged()
combinedChartViewOut.xAxis.valueFormatter = IndexAxisValueFormatter(values:months)
combinedChartViewOut.xAxis.granularity = 1
combinedChartViewOut.animate(xAxisDuration: 2.0, yAxisDuration: 2.0, easingOption: .easeInCirc)
}

Swift splitting "abc1.23.456.7890xyz" into "abc", "1", "23", "456", "7890" and "xyz"

In Swift on OS X I am trying to chop up the string "abc1.23.456.7890xyz" into these strings:
"abc"
"1"
"23"
"456"
"7890"
"xyz"
but when I run the following code I get the following:
=> "abc1.23.456.7890xyz"
(0,3) -> "abc"
(3,1) -> "1"
(12,4) -> "7890"
(16,3) -> "xyz"
which means that the application correctly found "abc", the first token "1", but then the next token found is "7890" (missing out "23" and "456") followed by "xyz".
Can anyone see how the code can be changed to find ALL of the strings (including "23" and "456")?
Many thanks in advance.
import Foundation
import XCTest
public
class StackOverflowTest: XCTestCase {
public
func testRegex() {
do {
let patternString = "([^0-9]*)([0-9]+)(?:\\.([0-9]+))*([^0-9]*)"
let regex = try NSRegularExpression(pattern: patternString, options: [])
let string = "abc1.23.456.7890xyz"
print("=> \"\(string)\"")
let range = NSMakeRange(0, string.characters.count)
regex.enumerateMatchesInString(string, options: [], range: range) {
(textCheckingResult, _, _) in
if let textCheckingResult = textCheckingResult {
for nsRangeIndex in 1 ..< textCheckingResult.numberOfRanges {
let nsRange = textCheckingResult.rangeAtIndex(nsRangeIndex)
let location = nsRange.location
if location < Int.max {
let startIndex = string.startIndex.advancedBy(location)
let endIndex = startIndex.advancedBy(nsRange.length)
let value = string[startIndex ..< endIndex]
print("\(nsRange) -> \"\(value)\"")
}
}
}
}
} catch {
}
}
}
It's all about your regex pattern. You want to find a series of contiguous letters or digits. Try this pattern instead:
let patternString = "([a-zA-Z]+|\\d+)"
alternative 'Swifty' way
let str = "abc1.23.456.7890xyz"
let chars = str.characters.map{ $0 }
enum CharType {
case Number
case Alpha
init(c: Character) {
self = .Alpha
if isNumber(c) {
self = .Number
}
}
func isNumber(c: Character)->Bool {
return "1234567890".characters.map{ $0 }.contains(c)
}
}
var tmp = ""
tmp.append(chars[0])
var type = CharType(c: chars[0])
for i in 1..<chars.count {
let c = CharType(c: chars[i])
if c != type {
tmp.append(Character("."))
}
tmp.append(chars[i])
type = c
}
tmp.characters.split(".", maxSplit: Int.max, allowEmptySlices: false).map(String.init)
// ["abc", "1", "23", "456", "7890", "xyz"]