<FromGitter>
<ImAHopelessDev_gitlab> is this the same thing i was talking about a long time ago
<FromGitter>
<ImAHopelessDev_gitlab> nvm, it's more to do with macros
deavmi has quit [Read error: Connection reset by peer]
dch has left #crystal-lang [#crystal-lang]
deavmi has joined #crystal-lang
ryanprior has joined #crystal-lang
erdnaxeli has joined #crystal-lang
psydroid has joined #crystal-lang
return0e[m] has joined #crystal-lang
f1refly has joined #crystal-lang
<f1refly>
If I where to implement a client for a REST api in crystal, what would be the best way to unit test it?
<f1refly>
Give the client a backend parameter where I can set it to either an http client for production use or to a specialized class that gives me access to the communitcation during testing?
<f1refly>
That was my first idea, are there better ways to do it?
<FromGitter>
<naqvis> mock class would only give you ability to test the logic, but you won't be able to simulate behaviors like network, io error etc
<FromGitter>
<naqvis> i would suggest to instantiate a http server in a spec and perform the testing
<FromGitter>
<naqvis> as that would simulate the real-world behavior
<f1refly>
Yeah, I had a look at how they test the http client itself in the crystal stdlib sources but I wasn't sure if it's appropriate to pretty much copy that for my client project
<f1refly>
Shouldn't I in theory be able to raise the same exceptions with my mock class though? The interfaces it implements would be the same as the http::client provides, so raising the same errors shouldn't be a problem, no?
<FromGitter>
<naqvis> thing is, your intention isn't to test the http::client
<FromGitter>
<j8r> @Blacksmoke16 the overhead can be considered marginal I guess
<FromGitter>
<Blacksmoke16> sure but you're also testing a lot more than you need/should be in a unit test. It's totally fine to want to test the whole flow, but at that point you shouldn't be calling it a unit test anymore
<FromGitter>
<j8r> test methods then
<FromGitter>
<Blacksmoke16> unit test would be more like mock the response from the api and ensure your client responds accordingly
<FromGitter>
<j8r> no need a framework for that
<FromGitter>
<j8r> the route calls methods, which can be unit tested
<FromGitter>
<Blacksmoke16> where does a route come into play for testing a REST API client?
<FromGitter>
<j8r> here i mean for the server
<FromGitter>
<j8r> but for the client too
<FromGitter>
<j8r> If performance really matters, just use a cache no?
<FromGitter>
<j8r> the mock is another thing to maintain :(
<FromGitter>
<Blacksmoke16> but a full server/cache wouldnt be?
<FromGitter>
<j8r> no, because it already exists
<FromGitter>
<Blacksmoke16> a mock is a lot simpler than that
<FromGitter>
<j8r> if one is making a client + server
<FromGitter>
<Blacksmoke16> all im saying is if you want to *unit* test your client it should be in isolation, using a mock so the only stuff you're testing is the client. If you dont want to use mocks you're not unit testing anymore (which is totally fine), but then no reason to unit test in addition to
<FromGitter>
<j8r> Yes that's not unit test anymore
<FromGitter>
<j8r> I prefer to actually run integration tests, just my take :)
<FromGitter>
<Blacksmoke16> it comes down to what exactly are you trying to test, the client itself, or the interaction with the client
<FromGitter>
<j8r> @aravindavk I see all this frameworks using different session stores. I think one generic library will do perfectly fine
<FromGitter>
<Blacksmoke16> hard part would be the integration into each framework as they're all designed differently
<FromGitter>
<j8r> for the store itself, I don't really see how
<FromGitter>
<Blacksmoke16> sorry i meant the interaction with the store, i.e. how to wire it up in the framework itself
<FromGitter>
<Blacksmoke16> but assuming the API is decent prob not too terribly hard
<FromGitter>
<j8r> at the end a session store is just storing a key, time and some value
<FromGitter>
<ilourt> Hello, I have a problem with Http server. It does not accept concurrent requests. In the following example I send to request one just after the other and normally both request shoudl respond nearly at the same time. But in this case the 2nd request is processed when the first one is finished
<FromGitter>
<j8r> @ImAHopelessDev_gitlab thanks, I guess. Most of people here don't do it :P
<FromGitter>
<j8r> I say "Happy (end of year) celebrations", so anyone of anywhere with any religion can be included ;)
<FromGitter>
<j8r> Except those that never celebrate anything...
<FromGitter>
<j8r> Anyway, I hope we will soon celebrate Crystal 1.0 together haha
<postmodern>
so if a crystal shard contains some optimized C code, is it perferred to make it optional (C vs. pure-crystal) or always build the C exts? is it safe to assume someone building a crystal project will also have a C compiler installed?
<postmodern>
j8r, also it's been one heck of a year. i'm sure everyone will be glad to put it behind them
<straight-shoota>
postmodern, what's the use case?
<straight-shoota>
it's probably hard to find a problem where optimizing C code is worth the trouble of being a bit faster than Crystal code.
<postmodern>
straight-shoota, optimizing digest-crc.cr, where the #update function get's pushed to C. Not sure what the communities opinion is of shards that contain custom bits of C.
<straight-shoota>
honestly, I've never heard of any shard that does that because there's little benefit
<straight-shoota>
C interop in Crystal is primarily useful for interfacing with existing libraries you don't need to reimplement in Crystal
<oprypin>
postmodern, there's also an array in-bounds check for @table[]
<postmodern>
oprypin, the @table variable is used by the methods inherited by CRC32
<straight-shoota>
they should use the constant directly instead
<oprypin>
ye
<straight-shoota>
LLVM probably optimizes that, though
<straight-shoota>
@table is never written
<oprypin>
i super duper doubt that
<postmodern>
there's issues with const lookup in crc.cr, which is why i had to use ivars
<straight-shoota>
just a hinch. LLVM does crazy stuff
<oprypin>
not when it affects the ABI
<straight-shoota>
using array for the table also adds overhead
<FromGitter>
<j8r> and a class_var?
<oprypin>
hm no i shouldnt speak on this. i'll just leave at my previous statement of "doubt it"
<straight-shoota>
no matter what, const is probably better
<oprypin>
table should be a staticarray or, if there are issues with that, just turn it into a pointer directly
<straight-shoota>
ivar is completely unneccesary
<straight-shoota>
if it doesn't matter performance wise, it matters for code quality
<postmodern>
suppose the fact that ruby C extensions were compiled with gcc, and crystal with clang, probably means different optimizations are being done, so not totally a fiar comparison
<FromGitter>
<j8r> postmodern using a Tuple with constant looks like to be more performant.
<FromGitter>
<j8r> Trying it now
<postmodern>
straight-shoota, the ivar is necessary for inheritence and DRYing up the code, which does improve code quality
<straight-shoota>
how's @table more DRY than TABLE ?
<oprypin>
yea constant inheritance is broken, but aren't we worrying about performance at the moment?
<postmodern>
straight-shoota, some of the CRC algorithm variations inherit from others, but override some data
<oprypin>
straight-shoota, probably cuz u cant use TABLE in subclasses
<postmodern>
straight-shoota, also worried about making sure the specs still pass ;)
<straight-shoota>
ah, I've only seen classes that use it directly
deavmi has quit [Quit: Eish! Load shedding.]
<FromGitter>
<Blacksmoke16> im pretty sure you can use constants in sub classes
<FromGitter>
<j8r> anyway, try to use tuples
deavmi has joined #crystal-lang
<straight-shoota>
@Blacksmoke16 the problem is when parent type defines method, it uses that type's constant
<postmodern>
Blacksmoke16, it's overriding them in the sub-class so that methods in the super-class use the overrided the constant, which is the problem
<straight-shoota>
a workaround for that could be a private method that returns the correctly scoped constant
<straight-shoota>
place that in the parent type and you can use table in any subtype referencing the correct const
<straight-shoota>
there should be a solution without a macro, but I'm not sure
<FromGitter>
<Blacksmoke16> this is prob why `PHP` has `static` and `self` be diff concepts
<straight-shoota>
yeah
kreyren has quit [Remote host closed the connection]
kreyren has joined #crystal-lang
<yxhuvud>
@straight-shoota: I remember asterite optimizing some cases of constant usage though, so putting things in instance variables *could* help noticeable unless you are running HEAD.
<yxhuvud>
ie it was after the relase of 0.35.1
_ht has quit [Quit: quit!]
<FromGitter>
<j8r> can we say that structs are 0 cost abstractions?
<yxhuvud>
as much as C structs are.
<yxhuvud>
(which is a yes, btw)
<jhass>
well I guess there's compile time cost
<yxhuvud>
and allocation/deallocation costs of some kind.
<oprypin>
i have a yielding method. can i call two parallel String.build using its results?
<straight-shoota>
IO::MultiWriter?
<oprypin>
wait why is this code borked? i know it's super weird but why https://carc.in/#/r/a0bh
<oprypin>
nvm im stupid. but yea this works but is super weird v
<straight-shoota>
yep, that would've been my suggestion
DTZUZU has joined #crystal-lang
<straight-shoota>
jhass, I replaced a couple of community:newcomer labels with community:help-wanted
<straight-shoota>
I don't think OpenSSL integration qualifies as newcomer friendly :)
<postmodern>
how does one specify multiple library names with @[Link(...)] for compatibility with different packages/distributions that name the library differently?
<oprypin>
oof
<jhass>
I tend to scope newcomer about "how much do you need to know about the project", so a big factor is how "self-contained" the change is. Say you're new to crystal but an expert in OpenSSL, something that redoes how we do TLS is not newcomer friendly as it needs to touch many parts of the project, meaning you need a good overview. Implementing say certificate chain validation OTOH is only
<jhass>
requiring a bare minimum of API design but deep knowledge of OpenSSL
<jhass>
so it could be quite friendly to such a "newcomer"
<straight-shoota>
that's true. But I suppose such spezialized newcomers will find their way to the relevant issues
<straight-shoota>
and OpenSSL integration also requires some amount of proficience in Crystal to even understand who the existing code works
<straight-shoota>
*how
<jhass>
well, it's all a judgement call, just trying to picture my gut feelings about this. The danger with scoping something like "newcomer" to small and easy tasks is that either those tasks stay unsolved unreasonably long because experienced contributors feels like they shouldn't take them away or that you simply don't have any tasks for newcomers at all making the entire idea moot
<FromGitter>
<j8r> small and easy, depends of the person
<FromGitter>
<j8r> I guess of the experienced dev point of view?
<jhass>
I just used OpenSSL as an illustration for how I think about this, I can't care to discuss the concrete example :)
<FromGitter>
<j8r> I mean, easy for newcomers, at least feasible for them
<jhass>
yes, for me it's really about "how feasible is this for somebody new to the codebase"
<jhass>
difficulty and time investment are secondary, I trust contributors to be able to judge if they can invest the time they need
<FromGitter>
<j8r> so why the issues would stay unresolved? I don't understand
<jhass>
the scenario was a different interpration of "necomer tasks" where you put scope and difficulty above feasibilty
<FromGitter>
<j8r> it's related to Crystal, to properly label issues?
<hightower2>
Any binary builds of 0.35.1 for arm64 available?
<jhass>
so that's an alternative route if the above doesn't work
<jhass>
looking at that I notice I borked the packages and forgot to remove the patch commands :D
<hightower2>
Well I guess I should put that crystal somewhere in path, not exactly in .build/crystal since if I put it there, it thinks the compiler is already compiled.
<hightower2>
But in any case, that build seems to be dynamic, and looking for libllvm-8, whereas the debian repository I use has 6, 7, 9, 10, and 11. No 8 :)
<hightower2>
so no dice.
<straight-shoota>
.build/crystal is to make the compiler use that to compile itself
<straight-shoota>
but you can just make it available as crystal in path, should do the same thing (unless there is a .build/crystal)
<hightower2>
hm, well if I put any executable into .build/crystal, `make` no longer does anything, thinking that the compiler is compiled.
<hightower2>
and if I do `make clean`, it removes the whole `.build` directory
<hightower2>
so I don't see how this can be a temporary compiler rather than the outcome of the build
<straight-shoota>
touch src
<straight-shoota>
but yeah, having it in path is enough
<straight-shoota>
the .build/crystal trick is used when you have a compiler in path but want to build using a different one
ua has joined #crystal-lang
<hightower2>
All evidence (i.e. contents of Makefile) seems to imply that .build/crystal is an outcome of the build, not a temporary stage. Do you mean to point me to ./bin/crystal to be the temporary binary, rather than .build/crystal ?
<straight-shoota>
no bin/crystal uses .build/crystal if it exists
<oprypin>
hightower2, it is true though that .build/crystal is an outcome of the build
<straight-shoota>
yes
<straight-shoota>
the general worklow is
<straight-shoota>
assuming crystal is in path und you have freshly checked out repo
<straight-shoota>
"make crystal" uses crystal vom path to build compiler in .build/crystal
<straight-shoota>
run "make crystal" again and it uses compiler from .build/crystal to build a new binary in .build/crystal
<hightower2>
ah yes, yes, ok clear now.
<straight-shoota>
but that whole .build/crystal thing just caused confusion. You don't need it. Just put the downloaded binary in path and run "make clear"
<hightower2>
now just to see if I can get libllvm-8 from somewhere.
<straight-shoota>
why not just use the static build?
<straight-shoota>
it comes with batteries included