-
Notifications
You must be signed in to change notification settings - Fork 816
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
Binary backend format support #41
Binary backend format support #41
Conversation
Added infrastructure to enable binary backend formatting. Added binary conversion handlers for int2, int4, and int8. Merged existing bytea binary support into new infrastructure, making it transparent. Renamed some of the conversion functions to be more descriptive.
…ns object Add copy constructor to NativeToBackendTypeConverterOptions. Keep distinct options object, initially == default, per connector.
…ding.GetChars, and new string(char[]) in favor of UTF8Encoding.GetString().
…l the copy constructor.
Added warning comment about E string prefix. ProcessServerVersion() now private, per FIXME.
Add internal flag that fully suppresses binary backend parameter and result formatting. Add reflection-based code to set and observer this flag in the test suite. Add a test that reports failure to bind to the flag. Add a couple tests that suppress binary backend encoding to make sure text encoding is tested on types that support binasy encoding.
facepalm Fixed... |
I just started to test here. I noticed that if you try to run the
I think this is because the BackendBinarySuppressor constructor expects an initialized SuppressBinaryBackendEncoding which is the case if I run the test suite but not if I run a single test. If I initialize the SuppressBinaryBackendEncoding variable directly, it works ok. The single test and the test suite.
|
Or we could add a call to |
That's why I had the initializer being called every time. |
I'm +1 to declare SuppressBinaryBackendEncoding with initializer directly. This would remove the need for _BindTo... method and would allow the tests to be independent from each other. |
If you do it in BuildUp(), and it throws, no tests will run at all. Maybe a good thing, maybe not? Not sure what you mean by eliminating _BindTo? This is why it was so complicated before, because every attempt to suppress included a check to see if init was yet needed on the FieldInfo :) |
I simplified the code a lot, so I think if I put back the init check into SuppressBackendBinary(), it will still be quite simple, and once again allow single tests to run properly. |
If you put the initializer in the variable, you won't need to keep the "This is why it was so complicated before, because every attempt to suppress included a check to see if init was yet needed on the FieldInfo :)" This is why I'm saying that you can be a little bit loose regarding the SuppressBinaryBackendEncoding initialization. It can't be null. This is an assumption of the test suite code you can make. There won't be any need to do checking if it is null or not. If the test fail because this field is null, there is something fundamentally wrong and should be fixed. |
And btw, your simplification is awesome. That's why I'm discussing with you in order to not put back those not null checks :) |
If the FieldInfo is null when a test tries to use it, and a test is not done to see if it's null, how will it get initialized? I think we're missing each other again somehow :( As I see it, we can either initialize on demand (what it did originally), or we can initialize in BuildUp() (which stops all tests from running on failure.) Any other way, and individual tests cannot use it. I can't tell which of those you're suggesting. Or maybe you mean to do the bind in BackendBinarySuppressor() constructor? But that seems expensive to me, which is why I avoided it in the first place. |
If instead of this line: https://github.com/franciscojunior/Npgsql2/pull/41/files#L6R74
you use
It will always be not null and will be able to be used in any test. There won't be any need for setup calls or other initializers. |
Ooooooohh lol... So that would mean a reflection failure would cause BaseClassTests construction to fail. Since I can't do try/catch there, I can't provide a more meaningful error. But if I write a default constructer and do it there, maybe it would be better. I will test failure modes and see how it looks. |
:) It is true that I'm assuming there won't be errors in the reflection call. I can't see any scenario this would happen unless a disruption in Npgsql like some change in the field name or access modifiers. And in this case, I think that a failure in the test would be enough. I think Nunit would be able to show any text the reflection call failure would generate, or if it silently returns an error and sets the field null, a lot of null reference exceptions will be thrown in the tests and we would be able to check what is the source of the problem. |
Just thought about another approach :
|
If I do what you suggested, and it fails, all tests fail, but no error information is provided. In don't understand that. If I do it in a default constructor wrapped in a try/catch/throw, all tests fail with the same exception. Pretty ugly in my opinion but at least that way a clue is provided. Nunit's behavior seems really odd here... I still like it better the way it is because one test with a descriptive name fails with a descriptive error, and then only the tests that try to suppress binary fail. And in fact, in SuppressBackendBinary(), we have the opportunity to privide yet another descriptive error (not just null reference). I'm kinda big on descriptive error reporting :) Sorry, didn't see that last comment. |
An exception thrown in SetUp() don't do what you think. No error is provided to the UI. Maybe you could do some testing. Add a throw or assert or something in SetUp(), run tests, and see what you think is going on there. It doesn't make any sense to me. |
Sure! I'll do it.
|
I did some tests here and I think the idea of assert in the setup provides the information we are looking for. This is what I did: Added this line to SetUp:
And then I run the tests and got this error message:
Then I added the line which initialize the Now, to simulate a problem where for some reason the field is not initialized correctly, I changed the line to this:
Note that I changed the name of the field to simulate a problem in the reflection call. Then I could test that the message is very clear and shows exactly where the problem is:
Of course this code won't tell you why the reflection code failed, but I think that if this happens, and unless it was a change by mistake of the field name, we would have a bigger problem than Npgsql tests. What do you think? |
Doesn't that cause every test to fail, even tests that don't attempt to suppress binary encoding? That's what happens when I do similar here. If I put the assert() in SuppressBackendBinary(), I get the somewhat-descriptive error, but only for tests that try to suppress. All others are unaffected. This also requires to out the binding within a try/catch that does not throw, which is why the detailed error info is lost I plagiarized your error message and will commit what I have now :) |
"By putting this initialization in SetUp, it will slow down all tests with reflection call. Even the ones which don't use BackendBinarySuppressor." Correct me if I'm wrong, but SetUp() is called just once per text fixture, right? So for CommandTests, it would be called once, and then nearly 200 tests would run without calling it again. |
Nope. That would be the SetUpFixtureAttribute I had a look at the SetUpFixtureAttribute but it requires the attribute to I learned about SetUpFixtureAttribute in this thread: while checking the documentation I found something which can help us This attribute is used inside a TestFixture to provide a single set of On Thu, Aug 15, 2013 at 12:31 PM, Glen Parker notifications@github.comwrote:
Regards, Francisco Figueiredo Jr. |
SetUp() is called before every test, which I did not realize. Now suppression initialization is called exactly once per fixture.
Refactored a bit the binary backend suppression. Added back a test which can provide descriptive error information if init fails. Error handling in InitBinaryBackendSuppression() is improved by avoiding a nebulous "null reference" exception.
Add Binary backend format support patch by Glen Parker Added infrastructure to enable binary backend formatting. Added binary conversion handlers for int2, int4, and int8. Merged existing bytea binary support into new infrastructure, making it transparent. Renamed some of the conversion functions to be more descriptive. Fix bug where all connectors were using the same type converter options object Add copy constructor to NativeToBackendTypeConverterOptions. Keep distinct options object, initially == default, per connector. Optimize away unneeded calls to UTF8Encoding.GetCharCount(), UTF8Encoding.GetChars, and new string(char[]) in favor of UTF8Encoding.GetString(). Binary test updates … Add internal flag that fully suppresses binary backend parameter and result formatting. Add reflection-based code to set and observer this flag in the test suite. Add a test that reports failure to bind to the flag. Add a couple tests that suppress binary backend encoding to make sure text encoding is tested on types that support binasy encoding.
Hi Francisco,
Since we're all synced up now, I made another branch for the binary backend format support I've been working on. The bytea and int support is in and all tests pass, so it should be ready for evaluation and merge.
-Glen