-
Notifications
You must be signed in to change notification settings - Fork 173
Fix tests (mostly ODBC) #676
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Conversation
… path instead Signed-off-by: Matt McNabb <[email protected]>
Signed-off-by: Matt McNabb <[email protected]>
Signed-off-by: Matt McNabb <[email protected]>
Signed-off-by: Matt McNabb <[email protected]>
Signed-off-by: Matt McNabb <[email protected]>
Signed-off-by: Matt McNabb <[email protected]>
…ot server date Signed-off-by: Matt McNabb <[email protected]>
Signed-off-by: Matt McNabb <[email protected]>
Signed-off-by: Matt McNabb <[email protected]>
Signed-off-by: Matt McNabb <[email protected]>
|
OK, the Linux build didn't like the change to defncopy test . As mentioned in the PR , the test didn't work in other operating systems because it hardcodes a path used by the Linux build system. Reviewing the build log -- the build installs |
Which operating systems are we talking about here? Tests should not use the installed binary, but the one compiled in the source directory, so the |
Talking about Windows build configured with I am hoping for a better solution than having to modify the C code of the test to build a path as defined by the build system, do you have any other ideas? |
… staging path instead" This reverts commit c149624. The fix did not work in the GitHub test container for Linux
|
@freddy77 I've reverted my "fix" for |
|
@freddy77 I have just noticed a mistake in my commit "ODBC - fix Hebrew/CN in Windows", the code I haven't pushed a fix as I am guessing from your commit to appveyor you might be working on fixing Windows iconv instead of accepting this workaround ? |
|
Yes, I fixed the iconv compilation to allow some other changes. Use of iconv is strongly recommended, that is not using it should be avoided. |
OK, I guess my change can still be accepted then? It will still test the iconv if they HAVE_ICONV but won't give error if they don't. |
yes |
| /* Compile-time check that sizes are defined correctly | ||
| * (otherwise the #if in odbc.h can malfunction) | ||
| */ | ||
| typedef char sizecheck_sqlwchar[(SIZEOF_SQLWCHAR == sizeof(SQLWCHAR)) ? 1 : -1]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Better to use TDS_COMPILE_CHECK macro, defined in freetds/macros.h.
| #if SIZEOF_SQLWCHAR != SIZEOF_WCHAR_T | ||
| size_t sqlwcslen(const SQLWCHAR * s); | ||
| #else | ||
| #define sqlwcslen(s) wcslen(s) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There's no mention of this change in the commit message
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I moved the definition of sqlwstr_buf and the SQLWSTR macros that use it, inside #ifdef ENABLE_ODBC_WIDE since they are not referenced outside of ENABLE_ODBC_WIDE ; but sqlwcslen needs to be outside that block as it is called without guards from sql2tds.c.
Re. the change in the same commit on sqlwchar.c -- IMHO it's more robust for sqlwchar.c to use #ifndef sqlwcslen, than repeat the tests from the header that led to sqlwcslen being defined (DRY principle)
| { 0, NULL, NULL }, | ||
| }; | ||
|
|
||
| static void hexdump(FILE* fp, char const* prefix, void const* p, size_t n) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
static void
hexdump(FILE* fp, const char* prefix, const void* p, size_t n)| static void hexdump(FILE* fp, char const* prefix, void const* p, size_t n) | ||
| { | ||
| fprintf(fp, "%s", prefix); | ||
| unsigned char const* cp = p; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just use p, no reason to create a copy. Also, do not mix declarations and code.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
in Standard C, pointer to void cannot be incremented or dereferenced - I prefer not to rely on compiler extensions if it's easily avoidable. But you could change the function signature , feel free to make cosmetic changes to my PR
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, I didn't see the implicit cast. Okay, just don't mix declarations and code, some compilers still complains.
| odbc_command("SELECT hebrew, cn FROM #tmp ORDER BY i"); | ||
|
|
||
| #else | ||
| fprintf(stderr, "Bypassing Hebrew MBCS test since iconv not installed (Forcing server to send UTF-8).\n"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The server will send UTF-16, not UTF-8, it's the client that converts to UTF-8, as built-in iconv supports both.
| case SQL_C_SBIGINT: | ||
| assert(in_len == sizeof(SQLBIGINT)); | ||
| sprintf(s, "%" PRId64, (int64_t) IN.bi); | ||
| sprintf(s, "%" PRId64, *(int64_t *)&IN.bi); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That expression is odd... the fact that int64_t and PRId64 exist means that a 64 bit type exists... but the pointer dereference seems to indicate IN.bi is not a number but possibly a structure. So it looks like some setting is wrong in the configuration.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This arose because of a mistake in UnixODBC sqltypes.h for my system that led to SQLBIGINT being defined as a struct containing two 32-bit ints , despite the fact that the compiler does support 64-bit ints. (I have since fixed sqltypes.h to use the 64-bit int on my system, that will be a separate PR for UnixODBC!).
But you are correct in your analysis that if the compiler does not support int64_t then my fix would not work , so let's just drop this change from the PR .
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you used Cmake probably this was needed ce7fad6 (already in master branch)
|
|
||
| return (*common_pwd.user && *common_pwd.server && *common_pwd.database) | ||
| /* (MM) user is not necessary for MSSQL trusted logins, for example */ | ||
| return (/* *common_pwd.user && */ *common_pwd.server && *common_pwd.database) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why left it commented out? Are you sure of the change?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well - if using MSSQL Trusted Connection then it is correct for user to be the empty string; the server authenticates based on your Windows user login identity. So in order to run the test suite against a MSSQL server that only uses Trusted Connection and not username/password login, the test should not require a username to be present . (I did run the test suite in this mode on my Windows system).
I'm presuming this code was in place to try and provide better diagnostics for when the user inadvertently forgot to configure PWD , however perhaps just checking for server and database still suits that need.
| read_login_info(); | ||
|
|
||
| return (*common_pwd.user && *common_pwd.server && *common_pwd.database) | ||
| /* (MM) user is not necessary for MSSQL trusted logins, for example */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would just say
/* user is not necessary for MSSQL trusted logins */| } | ||
| printf("Fake server bound at port %d\n", port); | ||
|
|
||
| setup_override(); /* Forces odbc_read_login_info() to find login details for our fake server instead */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
that's odd... why it works for me?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure... I am testing with TDSPWDFILE defined in my environment to point to the PWD for my test, are you doing the same? (as opposed to finding the hardcoded default path to PWD).
With the original order of these functions I get the output:
query : use TempDB
Line 1: unknown command 'use'
whereas with my suggested order, I get the output
query : use tempdb
Testing SQLFetch, line 425
and it proceeds to work correctly. Debugging in the fake thread proc shows that the original order receives as its first command use TempDB while the swapped order receives rowfmt, then row, then info etc. I am not sure where use TempDB is coming from.
In the original order it seems to me that the "override" details are never used -- because the first call to odbc_read_login_info sets common_pwd->initialized = true ; so even though setup_override is subsequently called which redefines TDSPWDFILE, the odbc_connect() call never reads the new TDSPWDFILE because of common_pwd->initialized already being set.
If I use the original order but insert common_pwd.initialized = common_pwd.tried_env = false; just before calling odbc_connect(), then the test works .
| /* Connect using SQLConnect() with Server, User and Password from PWD file | ||
| * NOTE: In Windows this looks up DSN in HKCU\Software\ODBC\ODBC.INI, with fallback to HKLM | ||
| */ | ||
| printf("SQLConnect(server=%s, ...) connect..\n", common_pwd.server); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
weird indentation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I probably don't have whitespace/tab settings configured properly in my editor to match your conventions for this project, please adjust to suit
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
don't worry, it's only a single instance
| sprintf(tmp, "DSN=%s;UID=%s;PWD=%s;DATABASE=%s;", common_pwd.server, | ||
| common_pwd.user, common_pwd.password, common_pwd.database); | ||
| CHKDriverConnect(NULL, T(tmp), SQL_NTS, (SQLTCHAR *) tmp, sizeof(tmp)/sizeof(SQLTCHAR), &len, SQL_DRIVER_NOPROMPT, "SI"); | ||
| /* note: final argument "SI" means CHKDriverConnect will exit() if the result is not Success or Sucess With Info */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
these strings are used everywhere, I would say it's base knowledge, the comment looks redundant to me
| common_pwd.user, common_pwd.password, common_pwd.database); | ||
| CHKDriverConnect(NULL, T(tmp), SQL_NTS, (SQLTCHAR *) tmp, sizeof(tmp)/sizeof(SQLTCHAR), &len, SQL_DRIVER_NOPROMPT, "SI"); | ||
| /* note: final argument "SI" means CHKDriverConnect will exit() if the result is not Success or Sucess With Info */ | ||
| rc = CHKDriverConnect(NULL, T(tmp), SQL_NTS, (SQLTCHAR *) tmp, sizeof(tmp)/sizeof(SQLTCHAR), &len, SQL_DRIVER_NOPROMPT, "SI"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
are you using rc value?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks like I'm not, must have inadvertently left that in after debugging why it was failing on my system.
| #ifdef _WIN32 | ||
| if (get_entry("SERVER")) { | ||
| init_connect(); | ||
| sprintf(tmp, | ||
| "DRIVER=FreeTDS;SERVER=%s;UID=%s;PWD=%s;DATABASE=%s;", | ||
| entry, common_pwd.user, common_pwd.password, common_pwd.database); | ||
| if (get_entry("TDS_Version")) | ||
| sprintf(strchr(tmp, 0), "TDS_Version=%s;", entry); | ||
| if (get_entry("Port")) | ||
| sprintf(strchr(tmp, 0), "Port=%s;", entry); | ||
| rc = CHKDriverConnect(NULL, T(tmp), SQL_NTS, (SQLTCHAR *) tmp, sizeof(tmp) / sizeof(SQLTCHAR), &len, | ||
| SQL_DRIVER_NOPROMPT, "SIE"); | ||
| if (rc == SQL_ERROR) { | ||
| printf("Unable to open data source (ret=%d)\n", rc); | ||
| } else { | ||
| ++succeeded; | ||
| } | ||
| odbc_disconnect(); | ||
| } | ||
| #endif |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why did you remove this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well, this test invokes SQLDriverConnect with DRIVER=FreeTDS , but typically that means it'll find the driver already installed on your system, unless you specifically modified the odbcinst.ini registry key to have an entry [FreeTDS] that points to the development driver we just built. Some of the tests have code for Linux to generate a temporary odbcinst.ini but Windows ODBC uses a registry key called Odbcinst.ini instead, it does not use environment variable ODBCINSTINI.
I decided to remove because: (a) as just described, this test is not testing what we just built; and (b) even if it did, the test is redundant with regard to the pass condition succeeded < 3 as there are also 3 other tests which should succeed. (Although maybe this is not actually the case for Sybase, I have only tested with MSSQL on this round).
| #ifdef _WIN32 | ||
| printf("Try from admin command prompt:\n\todbcconf /A {INSTALLDRIVER \"FreeTDS | Driver = C:\\Program Files(x86)\\FreeTDS\\bin\\tdsodbc.dll\"}" | ||
| "\n(replace path with your installation path for tdsodbc.dll if necessary)\n"); | ||
| #endif |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe for Windows we could use functions to add the driver? Like SQLInstallDriverEx ? Maybe using a different name like FreeTDS_test.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
FreeTDS_Test sounds like a good option to me -- then we would get helpful error messages instead of silently using the wrong driver. The same concept could perhaps be used in all of the "front door" tests (i.e. the ones that go in via SQLDriverConnect).
|
@freddy77 let me know how you'd like to proceed from here -- e.g. will you commit your own versions of my commits once you're happy (as you did for Issue 511 & the ASE bulk copy) , or if you want me to do anything else on this branch such as implement your suggestions? |
I'm pretty busy at the moment, so probably you will be faster than me. |
@freddy77 OK - and would you prefer new commits, or force-rewrite this branch with suggestions implemented ? |
I saw you easily added new commits. I can easily merge fixes before merging. Possibly asking you if I did a nice job. Not requiring to write fixup commits. |
Fixed a bunch of ODBC tests . Entire test suite now passes for me using SQL Server 2019 and 2022, in Linux and Windows (and VMS).
The test
a_defncopyfailed in Windows because it hardcoded invoking..\tsqlfrom the test binary location, but in Windows the binary directories are prefixed by the build type, so that path should be..\..\Debug\tsql.I fixed it by removing the path prefix, so it will grab a binary from the PATH. When we're running the test suite we should have staged what we just built onto PATH anyway (in Windows this lets it find all the needed DLLs; in Linux can be done by configure --prefix etc.)