Brightify / Cuckoo

Boilerplate-free mocking framework for Swift!
MIT License
1.66k stars 170 forks source link

Add support for Linux #26

Open TadeasKriz opened 8 years ago

lvdstam commented 7 years ago

Is there anybody interested? How would you go about it?

TadeasKriz commented 7 years ago

I think this is blocked by supporting Swift Package Manager. I'm not sure how would one go about using Cuckoo on Linux since there is no CocoaPods. This is something we'd like to add in the future.

kainjow commented 6 years ago

It appear using Swift PM is the way to do it on Linux. Also makes it easier for projects on the Mac to use without relying on CocoaPods (which has its issues).

MatyasKriz commented 4 years ago

We've added SwiftPM in 1.3.2, but I'm not sure if Linux has all the necessary things to fully support mocking with Cuckoo. I don't have any Linux on hand, so I'd be happy if someone tried this.

milosmns commented 4 years ago

@MatyasKriz Is it enough to try to build Cuckoo on Linux? If so, a Docker build should provide a proof of that, I have a Swift project that builds that way

MatyasKriz commented 4 years ago

@milosmns I am unfortunately completely out of my comfort zone here. I've never tried using Linux for developing anything in Swift and I'm not sure how I'd even go about compiling the project as a whole. Would you try compiling Cuckoo and perhaps try to make some adjustments that might make it compilable if it's not? In case it's something more serious, we can discuss the next steps here.

milosmns commented 4 years ago

Well... I tried, and it doesn't work. I'll explain in detail, but basically, I believe that it all comes down to Apple's marketing strategy about Swift being an open-source cross-platform language. A short disclaimer: I just recently started using Swift, and I think the language is ok. It has a bit of that Apple taste, stripping down and removing some necessary constructs... but fine. It just feels like Apple promises/proclaims more about their products than they really are (surprise).

To start, Foundation for Linux seems years away from being complete if they continue development at this pace. Take a look here - https://github.com/apple/swift-corelibs-foundation/blob/master/Docs/Status.md#implementation-status - a lot of stuff is not done, and the main Swift feature list just keeps growing. That's just one of the issues.

Having worked on many platforms in the past and using many different languages, I find Swift's support for multi-platform to be the worst, by far. Tooling for build and test actions is completely different on Linux vs. Mac, especially the stuff around running tests. Windows (the world's largest desktop platform) is not even supported... so, for example, Linux requires a file called LinuxMain.swift for each test group. This file specifies which files and tests should be executed during testing on Linux. It's super strange... no other mainstream language requires such a configuration. Fine, never mind, let's continue. There are some workarounds for that problem.

If you run swift test --generate-linuxmain, then the tooling should generate LinuxMain.swift files for you. Only, it doesn't work for Cuckoo for some reason, there's no git diff afterwards. And even if it did work, it requires a Mac machine with all XCode stuff installed to be able to run the command. I tried manually adding those files, but no luck there either, still fails with LinuxMain.swift missing.

Reading through these possible solutions, I found a very interesting solution using flags. Of course, it's not the default behavior, but it kind of works: swift test --enable-index-store --enable-test-discovery. From what I understood, it reads through the test files and generates a .build/ index that swift test command will use to discover tests.

OK, so, we're getting somewhere. This last command runs the tests, but the tests fail. To build Cuckoo, I added the same two flags, and it looks like it builds correctly (release & development variants). Here I don't understand why it builds when the tests are failing with compile errors...

Anyway, I prepared a Dockerfile which you can use to test on your machine. It should be super easy to configure:

1) Install Docker 2) Clone this repository 3) In the repository root add the Dockerfile from below. File name should be just Dockerfile

FROM milosmns/swift-vapor:5.2-bionic
# My base Ubuntu 18.04 image contains Swift 5.2 and server-side framework Vapor on top. I use it for my projects so I am 100% sure that Swift will work inside of it.

# Copy project files to /app
WORKDIR /app
COPY . .

# If Environment becomes necessary, this fixes the issue:
# ARG env
# ENV ENVIRONMENT=$env

# Build and test the project
RUN apt-get update \
    && mkdir -p /build/lib \
    && cp -R /usr/lib/swift/linux/*.so* /build/lib \
    && swift build --enable-index-store --enable-test-discovery --verbose \
    && swift build -c release --enable-index-store --enable-test-discovery --verbose \
    && swift test --enable-index-store --enable-test-discovery

4) From your Terminal, go to the repo root, run docker build .

One last observation: testing fails with compile errors around UITextView, WebKit and some other non-platform stuff. I'd say that this is related somehow to iOS or Mac development, and not essential... but I have limited experience with these platforms, so I'm just guessing.

If these tests are the only thing that's preventing us from using Cuckoo on ~other platforms~ Linux, then I'd argue that these tests and possibly their source and main functionality should be moved to an add-on project, or another "optional" layer somehow. This way we could be able to include the 'core' on both Linux and Mac, and people who develop for iOS/Mac only can include this optional mocking layer on top of 'core'.

@MatyasKriz Let me know what you think. I know I just dumped loads of info here, but I hope it will be helpful for you as you're familiar with the codebase. 😄

MatyasKriz commented 4 years ago

Hey, @milosmns! That's a very nicely detailed intro to testing Cuckoo on Linux. I'm grateful for your efforts as well as preparing the Dockerfile. I'll take a look at this in more depth as soon as I can.

Just skimming through the code, WebKit is only used in ObjectiveProtocolTest.swift which tests Cuckoo+OCMock functionality and the compiler directive #if os(iOS) should prevent that test suite from being ran.

However, I noticed just recently that I've forgotten to hide import WebKit behind this directive, so that might be one problem. As for the UITextField, I'm not sure why it's failing, that one is correctly enveloped in the compiler directive as far as I can tell.

Though, if there's no other way, we can just remove all the Cuckoo+OCMock tests in the RUN section of the Dockerfile before testing.

Thank you again for the detailed report and your efforts to run the tests! As mentioned, I'll jump into it when I can, probably within a week. Thanks to your research, it should be a breeze for me.

milosmns commented 4 years ago

Awesome, glad I could be of some help. Hopefully, the Foundation will progress on Linux as well so that we can have a truly cross-platform experience with Swift.

MatyasKriz commented 4 years ago

Alright, first of all, thanks again for the Dockerfile, sure helps having that prepared and just focusing on the Cuckoo side of things.

I've managed to get Cuckoo compilable as well as getting the tests to run.

SPOILERS The tests pass!

However, it's not really viable for the moment as it requires MockManager to inherit from NSObject for who knows what reason.

Then it requires removing all the OCMock tests, ObjCProtocol tests as well as the checks for correctly excluded classes.

I've switched the image to use the official swift:5.2.2 in hopes that it might fix the NSObject thing, but it didn't and I can't seem to find the source of the issue.

So, to successfully build and test Cuckoo on Linux, this Dockerfile based on @milosmns's one might be used:

FROM swift:5.2.2

# Copy project files to /app
WORKDIR /app
COPY . .

# If Environment becomes necessary, this fixes the issue:
# ARG env
# ENV ENVIRONMENT=$env

# Build and test the project
RUN apt-get update \
    && mkdir -p /build/lib \
    && cp -R /usr/lib/swift/linux/*.so* /build/lib \
    && rm -rf Tests/Swift/OCMock Tests/Swift/Source/ObjcProtocol.swift Tests/Swift/ExcludedStubTest.swift \
    && sed -i 's/class MockManager {/class MockManager: NSObject {/g' Source/MockManager.swift \
    && swift build --enable-index-store --enable-test-discovery \
    && swift build -c release --enable-index-store --enable-test-discovery \
    && swift test --enable-index-store --enable-test-discovery

Maybe I should mention that I'm building this on the latest branch feature/tuist.

It is fragile of course (and I've made the sed more restrictive, so it depends on MockManager being a class and not inheriting or conforming to anything). I don't really mind excluding the ObjC tests, but I don't really like the need to inherit from NSObject just for the sake of it, so I might try looking for a better solution if there is one.

I'd be happy if you looked into the matter as well if you have a hunch. Even if we can't solve this for now, the research and work you've done here will help future pioneers use Cuckoo on Linux. Thanks for that!

milosmns commented 4 years ago

Good to hear, that's some progress. Glad my noob Swift knowledge was of some help. 🙂

I'm kinda stuck now with some other stuff, but I'd like to continue digging when I get some time.

On Sun, Apr 26, 2020, 12:30 Matty Cross notifications@github.com wrote:

Alright, first of all, thanks again for the Dockerfile, sure helps having that prepared and just focusing on the Cuckoo side of things.

I've managed to get Cuckoo compilable as well as getting the tests to run. SPOILERS The tests pass!

However, it's not really viable for the moment as it requires MockManager to inherit from NSObject for who knows what reason.

Then it requires removing all the OCMock tests, ObjCProtocol tests as well as the checks for correctly excluded classes.

I've switched the image to use the official swift:5.2.2 in hopes that it might fix the NSObject thing, but it didn't and I can't seem to find the source of the issue.

So, to successfully build and test Cuckoo on Linux, this Dockerfile based on @milosmns https://github.com/milosmns's one might be used:

FROM swift:5.2.2

Copy project files to /app

WORKDIR /app COPY . .

If Environment becomes necessary, this fixes the issue:

ARG env

ENV ENVIRONMENT=$env

Build and test the project

RUN apt-get update \ && mkdir -p /build/lib \ && cp -R /usr/lib/swift/linux/.so /build/lib \ && rm -rf Tests/Swift/OCMock Tests/Swift/Source/ObjcProtocol.swift Tests/Swift/ExcludedStubTest.swift \ && sed -i 's/class MockManager {/class MockManager: NSObject {/g' Source/MockManager.swift \ && swift build --enable-index-store --enable-test-discovery \ && swift build -c release --enable-index-store --enable-test-discovery \ && swift test --enable-index-store --enable-test-discovery

Maybe I should mention that I'm building this on the latest branch feature/tuist.

It is fragile of course (and I've made the sed more restrictive, so it depends on MockManager being a class and not inheriting or conforming to anything). I don't really mind excluding the ObjC tests, but I don't really like the need to inherit from NSObject just for the sake of it, so I might try looking for a better solution if there is one.

I'd be happy if you looked into the matter as well if you have a hunch. Even if we can't solve this for now, the research and work you've done here will help future pioneers use Cuckoo on Linux. Thanks for that!

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/Brightify/Cuckoo/issues/26#issuecomment-619525385, or unsubscribe https://github.com/notifications/unsubscribe-auth/AANQTCQRXAXJOVG62T6BDCTROQELTANCNFSM4CGYSMQA .