container-structure-test icon indicating copy to clipboard operation
container-structure-test copied to clipboard

How we can test daemons?

Open dzavalkinolx opened this issue 7 years ago • 6 comments

I have a very simple container with nginx which serves static content. I want to verify that nginx starts with proper virtual host configuration and returns index.html with all headers properly set. Since this PR is merged With https://github.com/GoogleCloudPlatform/container-structure-test/pull/43 merged entrypoint is empty and my nginx is not started. I was trying to start nginx as a daemon or as a detached process but I can't see how to do it. Seems like all processes started in setup stage are killed?

With this code I see that no nginx is running

- name: "nginx is running and returns index.html page"
  setup: [["apk", "--no-cache", "add", "curl"], ["nginx"]]
  command: "ps"
  args: ["aux"]
  expectedOutput: ["nginx"]

Test result:

    --- FAIL: TestAll/Command_Test:_nginx_is_running_and_returns_index.html_page (3.90s)
        docker_driver.go:85: stdout: PID   USER     TIME   COMMAND
                    1 root       0:00 ps aux
        utils.go:33: Expected string 'nginx' not found in output!

I also tried to run nginx not as daemon but detached ["nginx", "-g", "daemon off", "&"] - test result is the same. If I run nginx in foreground with ["nginx", "-g", "daemon off", "&"] then setup commands is hanging. I think you should fix logic of the setup command to allow it spawn daemons, detached processes or maybe don't wait for it to finish before running main command (for foreground commands).

dzavalkinolx avatar Mar 08 '18 18:03 dzavalkinolx

After thinking about this issue again I believe you should revert #43. Basically, you change SUT when you override entrypoint - this is just conceptually wrong. Probably you can leave this option to override entrypoint but it should be opt-in, i.e. people can use it if their container are not testable otherwise but I think the general approach should be that people should change their container to make them testable. Like with unit testing for source code, instead of trying to mock dependency somewhere in private property of the class using reflection people should move dependency to the constructor.

dzavalkinolx avatar Mar 09 '18 08:03 dzavalkinolx

I think your case is close to https://github.com/GoogleCloudPlatform/container-structure-test/issues/53#issuecomment-361767823 and you are trying to do integration and not structure test.

zemanlx avatar Mar 09 '18 08:03 zemanlx

@zemanlx Well, from classical point of view it is and integration test. However, if we think about container as a unit then it is more like a unit test. I want to call class method, class here is container and method is that responds on the exposed port.

But it doesn't matter in the end. We need some generic solution to test application installed inside container. Before I discovered this project I used https://github.com/sstephenson/bats but it requires me to build a test images based on SUT image with bats installed. Also, tests written in bash aren't that readable that's why I'm very happy with this new tool.

dzavalkinolx avatar Mar 09 '18 22:03 dzavalkinolx

I'm building an image for my project [blockchain2graph]https://github.com/straumat/blockchain2graph) and I need to start a neo4j server in my docker image. I would like to do a neo4j status to check if my deamon is running. From what I understand here, it seems your tool is not made for that ? Is there a tool I should use to complete your tool or will you add this feature later ? Thanks

straumat avatar Mar 11 '18 20:03 straumat

Hey @dzavalkinolx, thanks for filing. As @zemanlx mentioned, I would say that what you're trying to do is more in the domain of integration rather than structure tests. However, I understand your use case and am currently trying to figure out how to support it.

I think the main issue here is I want the UX for more "integration" style tests to be more explicit, so I'm working out the best way to do that. I think for now I'll keep #43 in, and maybe work on supporting an option to specify an entrypoint for an image in the the yaml.

That said, I think I know why you're seeing the issue here. The Setup command runs commands and then commits their modified image to be the new base image for the test run, so things like running daemons get ignored. Having a specified entrypoint for the container should fix this.

nkubala avatar Mar 12 '18 01:03 nkubala

I know this is quite an old issue... but just wanted to share that we managed to do an "integration test" on a node server by doing the following, which I'd think would work for any daemon process:

commandTests:
  - name: 'server starts'
    command: 'bash'
    args:
      - '-c'
      - |
         /app/src/app > /home/node/output 2>&1 &
         sleep 1
         kill `pidof node`
         cat /home/node/output
    expectedOutput:
      - '.*Started server on port.*'

It works by:

  1. Running the app as a daemon with the output piped to a local file.
  2. Waiting enough time for the background app to run
  3. Killing the app
  4. Reading out the contents of the logfile to stdout

dpraul avatar May 24 '21 20:05 dpraul