So, I want SQL errors to prevent C++ code from building successfully.
What I was thinking was compiling via some cmake script or something that would grep the cpp files for SQL and validate the SQL.
I know I could add some kind of runtime error checking but I don't want the following code to build sucessfully (not a question about pqxx, but SQL errors in C++ in general):
#include <iostream>
#include <pqxx/pqxx>
using namespace std;
using namespace pqxx;
int main() {
connection conn("dbname=d user=u");
conn.prepare("invalid_sql", "SELECT 1 FROM WHERE a = $1");
nontransaction txn(conn);
txn.prepared("invalid_sql")(1.0).exec();
cout << "the process already died due to invalid SQL" << endl;
return 0;
}
You can, sort-of...
One approach is Boost meta_parsing, another is using C++11's user-defined literal types. I couldn't find a worked example for SQL, but perhaps as C++11 matures someone will come up with one.
Closing this question. The other answer is fine, but that's not what I did.
What I decided to do was put the prepared statements in a init_sql() method and call that using boost/test/unit_test.hpp against a replicated database with jenkins, which provides notifications for unit test failures.
Related
I am working on a hobby project mainly to learn cpp unit testing and database programming. However I am a little bit lost & confused about how should I write my code for proper testing. I tend to write a lot of void functions for my cpp projects. But now I can not figure out how should I test those functions. I have been succeeded in testing non-void functions cause they return something which can be easily tested against a value.
Ami I doing things in an unprofessional way? Should I avoid void functions as much as possible so that I can test those functions ? Or I am missing something ? For example how would I be able to test this function -
database.cpp
#include "database.hpp"
#include <sqlite3.h>
#include <iostream>
#include "spdlog/sinks/basic_file_sink.h"
// Creating the logging object
auto logger = spdlog::basic_logger_mt("appnotex", "../data/appnotexlog");
void Database::createDb(const char *dbname) {
// Creating the database file
sqlite3 *datadb;
int status = sqlite3_open(dbname, &datadb);
// checking for errors
if (status == SQLITE_OK) {
logger->info("------------ New Session ----------");
logger->info("Connected to Database Successfully");
} else {
std::string errorMessage = sqlite3_errmsg(datadb);
logger->info("Error: " + errorMessage);
}
If Needed
I am using Google Test framework
My whole project code hosted - here
Update
I have tried this one is this approach of testing the above method correct ?
databaseTest.cpp
TEST(DatabaseTest, createDbTest) {
const char *dbfilename = "../data/test/data.db";
const char *tbname = "DataTest";
Database *db = new Database();
std::ifstream dbfile("../data/test/data.db");
bool ok = false;
if (!dbfile.is_open())
ok = false;
else
ok = true;
EXPECT_TRUE(ok);
}
The problem is not so much in the function returning void. Think about how it signals errors and make sure all cases (success and failures) are tested, simple as that.
However, I don't see any error signalling at all there, apart from logging it. As a rule of thumb, logging should only be used for post-mortem research and the like. So, if logging completely fails, your program can still run correctly. That means, nothing internally depends on it and it is not a suitable error handling/signalling mechanism.
Now, there are basically three ways to signal errors:
Return values. Typically used in C code and sometimes used in C++ as well. With void return, that's not an option, and that is probably the source of your question.
Exceptions. You could throw std::runtime_error("DB connect failed"); and delegate handling it to the calling code.
Side effects. You could store the connection state in your Database instance. For completeness, using a global errno is also possible, but not advisable.
In any case, all three ways can be exercised and verified in unit tests.
In windows runtime component project (BackgroundTask c++)
#include "pch.h"
#include "BackgroundTask.h"
using namespace Platform;
namespace SyncBackground {
void BackgroundTask::Run(IBackgroundTaskInstance^ taskInstance) {
_taskInstance = taskInstance;
taskInstance->Canceled += ref new BackgroundTaskCanceledEventHandler(this, &BackgroundTask::OnCanceled);
_deferral = taskInstance->GetDeferral();
OutputDebugString(L"Debug: CPP\r\n");
}
void BackgroundTask::OnCanceled(IBackgroundTaskInstance^ sender, BackgroundTaskCancellationReason reason) {
_deferral->Complete();
}
}
I try ApplicationTrigger from c# project, but OutputDebugString write only one times from first trigger. In the same BackgroundTask C#, Debug.WriteLine() write every trigger.
Then why in c++ do it only one times? And how make it work look like c# (i need send some data and command via trigger)
Thank
I need it still run background
If I understand correctly, you just want to run background tasks indefinitely. If so, even if you don't call TaskDeferral.Complete();, it won't still run background, after a period of time, it will still be terminated. In that case, you can refer to this document to configure. But it mentions if you use it, you can't put an app into the Microsoft Store. If not, please point me out.
I am new to C++ (was previously into Java) and I am trying to find my way around it for the past few days. I am having a Sqlite DB in my local Machine which I am trying to access in order to display the results of a query on a Windows Application Form using DataGridView.
I was able to locate a good place to start here but later discovered that this was more concentrated towards SQL server and not SQLite and the code failed when I tried to replace this part of code
String^ connectionString =
"Integrated Security=SSPI;Persist Security Info=False;" +
"Initial Catalog=Northwind;Data Source=localhost";
with this
String^ connectionString = "Data Source=C:\\data\\test.db"
to point to my local Sqlite DB (test.db).
Upon more digging I found that I was able to find C# examples for linking SQLite DB to Windows Form Application here. Next I tried to convert the C# code provided into a C++ one but failed.
I have been looking all around for simple C++ examples which would help me understand how to link a Sqlite DB to a Windows Form Application but am not able to do so yet.
I would appreciate it greatly if anyone could point me to one such example.
To access SQLite DB from managed code use System.Data.SQLite library. It's a managed library supported by SQLite Development Team and you can use it with managed C++ also. Here is the sample:
using namespace System::Data::SQLite;
using namespace System::Text;
void Test()
{
SQLiteConnection ^db = gcnew SQLiteConnection();
try
{
db->ConnectionString = "Data Source=C:\\data\\test.db";
db->Open();
// Do the job here
db->Close();
}
finally
{
delete (IDisposable^)db;
}
}
The explanation of the problem is a little long-winded, please bear with me.
I have an unmanaged C++ static library that is used for financial application. It has business day conventions, swap conventions, bond conventions, etc. Most of the conventions rely on static global variables, which are initialized on first use. The library also initializes the holiday calendars on startup by running some queries against a SQL Server database using ODBC.
I have to interact with third-party software using web services. The only way to do this realistically is through C#. That isn't an issue, and I was making good progress. However, I hit a stumbling block when it became necessary to do some date calculations in C#. Since I didn't want to port all my C++ code to C#, I figured the most efficient way to achieve this would be by writing a Managed C++ Class Library DLL that is a wrapper around my unmanaged static library. Everything seems to work fine, I get no compile-time or link-time errors, and I can add the reference to the wrapper and see all the proper object definitions. However, when I try to run my application, it just hangs. I have tried playing around with a bunch of compiler setting for the wrapper DLL, to no avail. If I remove the project dependency on my unmanaged library, everything works fine. I have a strong suspicion that my liberal use of global static variables is causing issues. Is there are way to solve this problem, are at least figure out where the issue is? Example code is below.
Thanks,
Marc.
// FSAManaged.h
#pragma once
using namespace System;
//class XLDate;
namespace FSAManaged {
public ref class Futures
{
public:
static DateTime Expiry(String ^ code, DateTime date);
};
}
The implementation does not even rely on a dependency to the unmanaged static library:
// This is the main DLL file.
#include "stdafx.h"
#include "FSAManaged.h"
namespace FSAManaged
{
DateTime Futures::Expiry(String ^ code, DateTime date) {
return DateTime::Today;
}
}
For completeness' sake, here is AssemblyInfo.cpp:
#include "stdafx.h"
using namespace System;
using namespace System::Reflection;
using namespace System::Runtime::CompilerServices;
using namespace System::Runtime::InteropServices;
using namespace System::Security::Permissions;
//
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
//
[assembly:AssemblyTitleAttribute("FSAManaged")];
[assembly:AssemblyDescriptionAttribute("")];
[assembly:AssemblyConfigurationAttribute("")];
[assembly:AssemblyCompanyAttribute("?????")];
[assembly:AssemblyProductAttribute("FSAManaged")];
[assembly:AssemblyCopyrightAttribute("??????")];
[assembly:AssemblyTrademarkAttribute("")];
[assembly:AssemblyCultureAttribute("")];
//
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the value or you can default the Revision and Build Numbers
// by using the '*' as shown below:
[assembly:AssemblyVersionAttribute("1.0.*")];
[assembly:ComVisible(false)];
[assembly:CLSCompliantAttribute(true)];
[assembly:SecurityPermission(SecurityAction::RequestMinimum, UnmanagedCode = true)];
Use the debugger. If you test this from C# then Project + Properties, Debug, tick "Enabled unmanaged code debugging". Setting up the symbol server in Tools + Options, Debugging, Symbols is strongly recommended. Run.
When it hangs use Debug + Break All. Debug + Windows + Threads and double-click the thread that is supposed to be doing the job. Debug + Windows + Call stack to see what is going on. Post the stack trace in your question if you can't figure it out. Anything you see in the Output window and the Visual Studio status bar is relevant too.
Static C++ variables are initialized from DllMain. There are lot's of things you should not do in DllMain; triggering the load of yet another Dll being the most important one. This is easy to break if you call into other peoples libraries in from DllMain.
I suggest you make an Init function on your Dll, which you call after the dll is up and running.
This is a weird question in that I'm not sure where to start looking.
First of all, I haven't done any C++ programming for the last 10 years so it could be me thats forgotten a few things. Secondly, the IDE I'm using is Eclipse based (which I've never used) and customized for Samsung bada based mobile development (it kicks off an emulator for debugging purposes)
I'm posting my code samples as images because the StackOverflow WYSIWYG editor seems to have a problem parsing C++.
[EDIT] Due to complaints I've edited my question to remove the images. Hope that helps :)
I have the following header file...
#include <FApp.h>
#include <FBase.h>
#include <FGraphics.h>
#include <FSystem.h>
#include <FMedia.h>
using namespace Osp::Media;
using namespace Osp::Graphics;
class NineAcross :
public Osp::App::Application,
public Osp::System::IScreenEventListener
{
public:
static Osp::App::Application* CreateInstance(void);
public:
NineAcross();
~NineAcross();
public:
bool OnAppInitializing(Osp::App::AppRegistry& appRegistry);
private:
Image *_problematicDecoder;
};
...and the following cpp file...
#include "NineAcross.h"
using namespace Osp::App;
using namespace Osp::Base;
using namespace Osp::System;
using namespace Osp::Graphics;
using namespace Osp::Media;
NineAcross::NineAcross()
{
}
NineAcross::~NineAcross()
{
}
Application* NineAcross::CreateInstance(void)
{
// Create the instance through the constructor.
return new NineAcross();
}
bool NineAcross::OnAppInitializing(AppRegistry& appRegistry)
{
Image *workingDecoder;
workingDecoder->Construct();
_problematicDecoder->Construct();
return true;
}
Now, in my cpp file, if I comment out the line that reads _problematicDecoder->Construct();...I'm able to set a breakpoint and happily step over the call to Constuct() on workingDecoder. However, as soon as I uncomment the line that reads _problematicDecoder->Construct();... I end up with the IDE telling me...
"No source available for "Osp::Media::Image::Construct()"
In other words, why can I NOT debug this code when I reference Image *image from a header file?
Any ideas?
Thanks :-)
This usually means you're stepping through some code which you do not posses its source.
I assume here that Osp::Media::Image is a class supplied by Samsung or similar for which you do not have the cpp file. So this means the debugger can't show you the current code line while you're at a function of Osp::Media::Image.
Alternatively, there's a good chance you do have all of the source code for this class, but Eclipse doesn't know where it is. In this case you can add the correct directories under the Debug Configurations window.
Ok, problem solved.
The idea is to first new up an instance of Image like so...
_decoder = new Osp::Media::Image();
And then do _decoder->Construct().
Funny enough, this seems blatantly obvious to me now coming from the C# world, though why the code I posted for workingDecoder works is still somewhat mysterious to me. The fact the sample projects pre-loaded with the bada IDE don't seem to make a call to new() leads me to believe that perhaps those samples are outdated our out of synch.
Either that or I really AM wildly out of the C++ loop.
Anyway thanks so much for the effort guys.
Appreciated :)