Message ID | 20190306024755.28726-6-niklas.soderlund@ragnatech.se |
---|---|
State | Superseded |
Headers | show |
Series |
|
Related | show |
Hi Niklas, Thank you for the patch. On Wed, Mar 06, 2019 at 03:47:55AM +0100, Niklas Söderlund wrote: > Add a test of the different access level enforced by the state machine > inside the camera. The state machine aims to limit operations on the > camera to the cameras state. > > The test exercises all states of the camera and verifies that only the > intended operations are possible at each stage. > > Signed-off-by: Niklas Söderlund <niklas.soderlund@ragnatech.se> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Nice work ! > --- > test/camera/meson.build | 1 + > test/camera/statemachine.cpp | 275 +++++++++++++++++++++++++++++++++++ > 2 files changed, 276 insertions(+) > create mode 100644 test/camera/statemachine.cpp > > diff --git a/test/camera/meson.build b/test/camera/meson.build > index 6da297714f34a4e3..8f1cfe5a7a5c2884 100644 > --- a/test/camera/meson.build > +++ b/test/camera/meson.build > @@ -3,6 +3,7 @@ > camera_tests = [ > [ 'format_default', 'format_default.cpp' ], > [ 'format_set', 'format_set.cpp' ], > + [ 'statemachine', 'statemachine.cpp' ], > [ 'capture', 'capture.cpp' ], > ] > > diff --git a/test/camera/statemachine.cpp b/test/camera/statemachine.cpp > new file mode 100644 > index 0000000000000000..f4395f2b1bfed698 > --- /dev/null > +++ b/test/camera/statemachine.cpp > @@ -0,0 +1,275 @@ > +/* SPDX-License-Identifier: GPL-2.0-or-later */ > +/* > + * Copyright (C) 2019, Google Inc. > + * > + * libcamera Camera API tests > + */ > + > +#include <iostream> > + > +#include "camera_test.h" > + > +using namespace std; > + > +namespace { > + > +class Statemachine : public CameraTest > +{ > +protected: > + int testAvailable() > + { > + /* Test operations which should fail. */ > + if (camera_->configureStreams(defconf_) != -EACCES) > + return TestFail; > + > + if (camera_->allocateBuffers() != -EACCES) > + return TestFail; > + > + if (camera_->freeBuffers() != -EACCES) > + return TestFail; > + > + if (camera_->createRequest()) > + return TestFail; > + > + if (camera_->start() != -EACCES) > + return TestFail; > + > + Request request(camera_.get()); > + if (camera_->queueRequest(&request) != -EACCES) > + return TestFail; > + > + if (camera_->stop() != -EACCES) > + return TestFail; > + > + /* Test operations which should pass. */ > + if (camera_->release()) > + return TestFail; > + > + /* Test valid state transitions, end in Acquired state. */ > + if (camera_->acquire()) > + return TestFail; > + > + return TestPass; > + } > + > + int testAcquired() > + { > + /* Test operations which should fail. */ > + if (camera_->acquire() != -EBUSY) > + return TestFail; > + > + if (camera_->allocateBuffers() != -EACCES) > + return TestFail; > + > + if (camera_->freeBuffers() != -EACCES) > + return TestFail; > + > + if (camera_->createRequest()) > + return TestFail; > + > + if (camera_->start() != -EACCES) > + return TestFail; > + > + Request request(camera_.get()); > + if (camera_->queueRequest(&request) != -EACCES) > + return TestFail; > + > + if (camera_->stop() != -EACCES) > + return TestFail; > + > + /* Test valid state transitions, end in Configured state. */ > + if (camera_->release()) > + return TestFail; > + > + if (camera_->acquire()) > + return TestFail; > + > + if (camera_->configureStreams(defconf_)) > + return TestFail; > + > + return TestPass; > + } > + > + int testConfigured() > + { > + /* Test operations which should fail. */ > + if (camera_->acquire() != -EBUSY) > + return TestFail; > + > + if (camera_->freeBuffers() != -EACCES) > + return TestFail; > + > + if (camera_->createRequest()) > + return TestFail; > + > + Request request(camera_.get()); > + if (camera_->queueRequest(&request) != -EACCES) > + return TestFail; > + > + if (camera_->start() != -EACCES) > + return TestFail; > + > + if (camera_->stop() != -EACCES) > + return TestFail; > + > + /* Test operations which should pass. */ > + if (camera_->configureStreams(defconf_)) > + return TestFail; > + > + /* Test valid state transitions, end in Prepared state. */ > + if (camera_->release()) > + return TestFail; > + > + if (camera_->acquire()) > + return TestFail; > + > + if (camera_->configureStreams(defconf_)) > + return TestFail; > + > + if (camera_->allocateBuffers()) > + return TestFail; > + > + return TestPass; > + } > + > + int testPrepared() > + { > + /* Test operations which should fail. */ > + if (camera_->acquire() != -EBUSY) > + return TestFail; > + > + if (camera_->release() != -EBUSY) > + return TestFail; > + > + if (camera_->configureStreams(defconf_) != -EACCES) > + return TestFail; > + > + if (camera_->allocateBuffers() != -EACCES) > + return TestFail; > + > + Request request1(camera_.get()); > + if (camera_->queueRequest(&request1) != -EACCES) > + return TestFail; > + > + if (camera_->stop() != -EACCES) > + return TestFail; > + > + /* Test operations which should pass. */ > + Request *request2 = camera_->createRequest(); > + if (!request2) > + return TestFail; > + > + /* Never handed to hardware so need to manually delete it. */ > + delete request2; > + > + /* Test valid state transitions, end in Running state. */ > + if (camera_->freeBuffers()) > + return TestFail; > + > + if (camera_->release()) > + return TestFail; > + > + if (camera_->acquire()) > + return TestFail; > + > + if (camera_->configureStreams(defconf_)) > + return TestFail; > + > + if (camera_->allocateBuffers()) > + return TestFail; > + > + if (camera_->start()) > + return TestFail; > + > + return TestPass; > + } > + > + int testRuning() > + { > + /* Test operations which should fail. */ > + if (camera_->acquire() != -EBUSY) > + return TestFail; > + > + if (camera_->release() != -EBUSY) > + return TestFail; > + > + if (camera_->configureStreams(defconf_) != -EACCES) > + return TestFail; > + > + if (camera_->allocateBuffers() != -EACCES) > + return TestFail; > + > + if (camera_->freeBuffers() != -EACCES) > + return TestFail; > + > + if (camera_->start() != -EACCES) > + return TestFail; > + > + /* Test operations which should pass. */ > + Request *request = camera_->createRequest(); > + if (!request) > + return TestFail; > + > + Stream *stream = *camera_->streams().begin(); > + BufferPool &pool = stream->bufferPool(); > + Buffer &buffer = pool.buffers().front(); > + std::map<Stream *, Buffer *> map = { { stream, &buffer } }; > + if (request->setBuffers(map)) > + return TestFail; > + > + if (camera_->queueRequest(request)) > + return TestFail; > + > + /* Test valid state transitions, end in Available state. */ > + if (camera_->stop()) > + return TestFail; > + > + if (camera_->freeBuffers()) > + return TestFail; > + > + if (camera_->release()) > + return TestFail; > + > + return TestPass; > + } > + > + int run() > + { > + Stream *stream = *camera_->streams().begin(); > + std::set<Stream *> streams = { stream }; > + defconf_ = camera_->streamConfiguration(streams); > + > + if (testAvailable() != TestPass) { > + cout << "State machine in Available state failed" << endl; > + return TestFail; > + } > + > + if (testAcquired() != TestPass) { > + cout << "State machine in Acquired state failed" << endl; > + return TestFail; > + } > + > + if (testConfigured() != TestPass) { > + cout << "State machine in Configured state failed" << endl; > + return TestFail; > + } > + > + if (testPrepared() != TestPass) { > + cout << "State machine in Prepared state failed" << endl; > + return TestFail; > + } > + > + if (testRuning() != TestPass) { > + cout << "State machine in Running state failed" << endl; > + return TestFail; > + } > + > + return TestPass; > + } > + > + std::map<Stream *, StreamConfiguration> defconf_; > +}; > + > +} /* namespace */ > + > +TEST_REGISTER(Statemachine);
diff --git a/test/camera/meson.build b/test/camera/meson.build index 6da297714f34a4e3..8f1cfe5a7a5c2884 100644 --- a/test/camera/meson.build +++ b/test/camera/meson.build @@ -3,6 +3,7 @@ camera_tests = [ [ 'format_default', 'format_default.cpp' ], [ 'format_set', 'format_set.cpp' ], + [ 'statemachine', 'statemachine.cpp' ], [ 'capture', 'capture.cpp' ], ] diff --git a/test/camera/statemachine.cpp b/test/camera/statemachine.cpp new file mode 100644 index 0000000000000000..f4395f2b1bfed698 --- /dev/null +++ b/test/camera/statemachine.cpp @@ -0,0 +1,275 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * Copyright (C) 2019, Google Inc. + * + * libcamera Camera API tests + */ + +#include <iostream> + +#include "camera_test.h" + +using namespace std; + +namespace { + +class Statemachine : public CameraTest +{ +protected: + int testAvailable() + { + /* Test operations which should fail. */ + if (camera_->configureStreams(defconf_) != -EACCES) + return TestFail; + + if (camera_->allocateBuffers() != -EACCES) + return TestFail; + + if (camera_->freeBuffers() != -EACCES) + return TestFail; + + if (camera_->createRequest()) + return TestFail; + + if (camera_->start() != -EACCES) + return TestFail; + + Request request(camera_.get()); + if (camera_->queueRequest(&request) != -EACCES) + return TestFail; + + if (camera_->stop() != -EACCES) + return TestFail; + + /* Test operations which should pass. */ + if (camera_->release()) + return TestFail; + + /* Test valid state transitions, end in Acquired state. */ + if (camera_->acquire()) + return TestFail; + + return TestPass; + } + + int testAcquired() + { + /* Test operations which should fail. */ + if (camera_->acquire() != -EBUSY) + return TestFail; + + if (camera_->allocateBuffers() != -EACCES) + return TestFail; + + if (camera_->freeBuffers() != -EACCES) + return TestFail; + + if (camera_->createRequest()) + return TestFail; + + if (camera_->start() != -EACCES) + return TestFail; + + Request request(camera_.get()); + if (camera_->queueRequest(&request) != -EACCES) + return TestFail; + + if (camera_->stop() != -EACCES) + return TestFail; + + /* Test valid state transitions, end in Configured state. */ + if (camera_->release()) + return TestFail; + + if (camera_->acquire()) + return TestFail; + + if (camera_->configureStreams(defconf_)) + return TestFail; + + return TestPass; + } + + int testConfigured() + { + /* Test operations which should fail. */ + if (camera_->acquire() != -EBUSY) + return TestFail; + + if (camera_->freeBuffers() != -EACCES) + return TestFail; + + if (camera_->createRequest()) + return TestFail; + + Request request(camera_.get()); + if (camera_->queueRequest(&request) != -EACCES) + return TestFail; + + if (camera_->start() != -EACCES) + return TestFail; + + if (camera_->stop() != -EACCES) + return TestFail; + + /* Test operations which should pass. */ + if (camera_->configureStreams(defconf_)) + return TestFail; + + /* Test valid state transitions, end in Prepared state. */ + if (camera_->release()) + return TestFail; + + if (camera_->acquire()) + return TestFail; + + if (camera_->configureStreams(defconf_)) + return TestFail; + + if (camera_->allocateBuffers()) + return TestFail; + + return TestPass; + } + + int testPrepared() + { + /* Test operations which should fail. */ + if (camera_->acquire() != -EBUSY) + return TestFail; + + if (camera_->release() != -EBUSY) + return TestFail; + + if (camera_->configureStreams(defconf_) != -EACCES) + return TestFail; + + if (camera_->allocateBuffers() != -EACCES) + return TestFail; + + Request request1(camera_.get()); + if (camera_->queueRequest(&request1) != -EACCES) + return TestFail; + + if (camera_->stop() != -EACCES) + return TestFail; + + /* Test operations which should pass. */ + Request *request2 = camera_->createRequest(); + if (!request2) + return TestFail; + + /* Never handed to hardware so need to manually delete it. */ + delete request2; + + /* Test valid state transitions, end in Running state. */ + if (camera_->freeBuffers()) + return TestFail; + + if (camera_->release()) + return TestFail; + + if (camera_->acquire()) + return TestFail; + + if (camera_->configureStreams(defconf_)) + return TestFail; + + if (camera_->allocateBuffers()) + return TestFail; + + if (camera_->start()) + return TestFail; + + return TestPass; + } + + int testRuning() + { + /* Test operations which should fail. */ + if (camera_->acquire() != -EBUSY) + return TestFail; + + if (camera_->release() != -EBUSY) + return TestFail; + + if (camera_->configureStreams(defconf_) != -EACCES) + return TestFail; + + if (camera_->allocateBuffers() != -EACCES) + return TestFail; + + if (camera_->freeBuffers() != -EACCES) + return TestFail; + + if (camera_->start() != -EACCES) + return TestFail; + + /* Test operations which should pass. */ + Request *request = camera_->createRequest(); + if (!request) + return TestFail; + + Stream *stream = *camera_->streams().begin(); + BufferPool &pool = stream->bufferPool(); + Buffer &buffer = pool.buffers().front(); + std::map<Stream *, Buffer *> map = { { stream, &buffer } }; + if (request->setBuffers(map)) + return TestFail; + + if (camera_->queueRequest(request)) + return TestFail; + + /* Test valid state transitions, end in Available state. */ + if (camera_->stop()) + return TestFail; + + if (camera_->freeBuffers()) + return TestFail; + + if (camera_->release()) + return TestFail; + + return TestPass; + } + + int run() + { + Stream *stream = *camera_->streams().begin(); + std::set<Stream *> streams = { stream }; + defconf_ = camera_->streamConfiguration(streams); + + if (testAvailable() != TestPass) { + cout << "State machine in Available state failed" << endl; + return TestFail; + } + + if (testAcquired() != TestPass) { + cout << "State machine in Acquired state failed" << endl; + return TestFail; + } + + if (testConfigured() != TestPass) { + cout << "State machine in Configured state failed" << endl; + return TestFail; + } + + if (testPrepared() != TestPass) { + cout << "State machine in Prepared state failed" << endl; + return TestFail; + } + + if (testRuning() != TestPass) { + cout << "State machine in Running state failed" << endl; + return TestFail; + } + + return TestPass; + } + + std::map<Stream *, StreamConfiguration> defconf_; +}; + +} /* namespace */ + +TEST_REGISTER(Statemachine);
Add a test of the different access level enforced by the state machine inside the camera. The state machine aims to limit operations on the camera to the cameras state. The test exercises all states of the camera and verifies that only the intended operations are possible at each stage. Signed-off-by: Niklas Söderlund <niklas.soderlund@ragnatech.se> --- test/camera/meson.build | 1 + test/camera/statemachine.cpp | 275 +++++++++++++++++++++++++++++++++++ 2 files changed, 276 insertions(+) create mode 100644 test/camera/statemachine.cpp