Docs/tutorial: Wrap the text in part?.md to 72 characters
Signed-off-by: Martin Roth <gaumless@gmail.com> Change-Id: I4f0a07b4ab729aafdb4a1149a7617cd34392cf12 Reviewed-on: https://review.coreboot.org/c/coreboot/+/64967 Tested-by: build bot (Jenkins) <no-reply@coreboot.org> Reviewed-by: Elyes Haouas <ehaouas@noos.fr>
This commit is contained in:
parent
25aeaac85b
commit
d2c3e26513
|
@ -2,11 +2,11 @@ Tutorial, part 1: Starting from scratch
|
|||
===========================================
|
||||
|
||||
This tutorial will guide you through the process of setting up a working
|
||||
coreboot toolchain. In same cases you will find specific instructions for Debian (apt-get),
|
||||
Fedora (dnf) and Arch Linux (pacman) based package management systems. Use the
|
||||
instructions according to your system.
|
||||
coreboot toolchain. In same cases you will find specific instructions
|
||||
for Debian (apt-get), Fedora (dnf) and Arch Linux (pacman) based package
|
||||
management systems. Use the instructions according to your system.
|
||||
|
||||
** Note: Summaries of each of the steps are at the end of the document. **
|
||||
**Note: Summaries of each of the steps are at the end of the document.**
|
||||
|
||||
|
||||
Download, configure, and build coreboot
|
||||
|
@ -16,13 +16,15 @@ Download, configure, and build coreboot
|
|||
### Step 1 - Install tools and libraries needed for coreboot
|
||||
|
||||
Debian based distros:
|
||||
`sudo apt-get install -y bison build-essential curl flex git gnat libncurses5-dev m4 zlib1g-dev`
|
||||
`sudo apt-get install -y bison build-essential curl flex git gnat`
|
||||
`libncurses5-dev m4 zlib1g-dev`
|
||||
|
||||
Arch based distros:
|
||||
`sudo pacman -S base-devel curl git gcc-ada ncurses zlib`
|
||||
|
||||
Redhat based distros:
|
||||
`sudo dnf install git make gcc-gnat flex bison xz bzip2 gcc g++ ncurses-devel wget zlib-devel patch`
|
||||
`sudo dnf install git make gcc-gnat flex bison xz bzip2 gcc g++`
|
||||
`ncurses-devel wget zlib-devel patch`
|
||||
|
||||
|
||||
### Step 2 - Download coreboot source tree
|
||||
|
@ -36,8 +38,8 @@ cd coreboot
|
|||
|
||||
### Step 3 - Build the coreboot toolchain
|
||||
|
||||
Please note that this can take a significant amount of time. Use `CPUS=` to
|
||||
specify number of `make` jobs to run in parallel.
|
||||
Please note that this can take a significant amount of time. Use `CPUS=`
|
||||
to specify number of `make` jobs to run in parallel.
|
||||
|
||||
This will list toolchain options and supported architectures:
|
||||
|
||||
|
@ -53,12 +55,12 @@ make crossgcc-aarch64 CPUS=$(nproc) # build Aarch64 toolchain
|
|||
make crossgcc-riscv CPUS=$(nproc) # build RISC-V toolchain
|
||||
```
|
||||
|
||||
Note that the i386 toolchain is currently used for all x86 platforms, including
|
||||
x86_64.
|
||||
Note that the i386 toolchain is currently used for all x86 platforms,
|
||||
including x86_64.
|
||||
|
||||
Also note that you can possibly use your system toolchain, but the results are
|
||||
not reproducible, and may have issues, so this is not recommended. See step 5
|
||||
to use your system toolchain.
|
||||
Also note that you can possibly use your system toolchain, but the
|
||||
results are not reproducible, and may have issues, so this is not
|
||||
recommended. See step 5 to use your system toolchain.
|
||||
|
||||
|
||||
### Step 4 - Build the payload - coreinfo
|
||||
|
@ -117,7 +119,8 @@ make savedefconfig
|
|||
cat defconfig
|
||||
```
|
||||
|
||||
There should only be two lines (or 3 if you're using the system toolchain):
|
||||
There should only be two lines (or 3 if you're using the system
|
||||
toolchain):
|
||||
|
||||
```Text
|
||||
CONFIG_PAYLOAD_ELF=y
|
||||
|
@ -134,8 +137,8 @@ At the end of the build, you should see:
|
|||
|
||||
`Build emulation/qemu-i440fx (QEMU x86 i440fx/piix4)``
|
||||
|
||||
This means your build was successful. The output from the build is in the build
|
||||
directory. build/coreboot.rom is the full rom file.
|
||||
This means your build was successful. The output from the build is in
|
||||
the build directory. build/coreboot.rom is the full rom file.
|
||||
|
||||
|
||||
Test the image using QEMU
|
||||
|
@ -157,8 +160,8 @@ Start QEMU, and point it to the ROM you just built:
|
|||
qemu-system-x86_64 -bios build/coreboot.rom -serial stdio
|
||||
```
|
||||
|
||||
You should see the serial output of coreboot in the original console window, and
|
||||
a new window will appear running the coreinfo payload.
|
||||
You should see the serial output of coreboot in the original console
|
||||
window, and a new window will appear running the coreinfo payload.
|
||||
|
||||
|
||||
Summary
|
||||
|
@ -168,10 +171,10 @@ Summary
|
|||
### Step 1 summary - Install tools and libraries needed for coreboot
|
||||
|
||||
Depending on your distribution you have installed the minimum additional
|
||||
software requirements to continue with downloading and building coreboot.
|
||||
Not every distribution has the tools, that would be required,
|
||||
installed by default. In the following we shortly introduce the purpose of the
|
||||
installed packages:
|
||||
software requirements to continue with downloading and building
|
||||
coreboot. Not every distribution has the tools, that would be required,
|
||||
installed by default. In the following we shortly introduce the purpose
|
||||
of the installed packages:
|
||||
|
||||
* `build-essential` or `base-devel` are the basic tools for building software.
|
||||
* `git` is needed to download coreboot from the coreboot git repository.
|
||||
|
@ -180,67 +183,72 @@ installed packages:
|
|||
are needed to build the coreboot toolchain. `gcc` and `gnat` have to be
|
||||
of the same version.
|
||||
|
||||
If you started with a different distribution or package management system you
|
||||
might need to install other packages. Most likely they are named slightly
|
||||
different. If that is the case for you, we'd like to encourage you to contribute
|
||||
to the project and submit a pull request with an update for this documentation
|
||||
for your system.
|
||||
If you started with a different distribution or package management
|
||||
system you might need to install other packages. Most likely they are
|
||||
named slightly different. If that is the case for you, we'd like to
|
||||
encourage you to contribute to the project and submit a pull request
|
||||
with an update for this documentation for your system.
|
||||
|
||||
|
||||
### Step 2 summary - Download coreboot source tree
|
||||
|
||||
This will download a 'read-only' copy of the coreboot tree. This just means
|
||||
that if you made changes to the coreboot tree, you couldn't immediately
|
||||
contribute them back to the community. To pull a copy of coreboot that would
|
||||
allow you to contribute back, you would first need to sign up for an account on
|
||||
gerrit.
|
||||
This will download a 'read-only' copy of the coreboot tree. This just
|
||||
means that if you made changes to the coreboot tree, you couldn't
|
||||
immediately contribute them back to the community. To pull a copy of
|
||||
coreboot that would allow you to contribute back, you would first need
|
||||
to sign up for an account on gerrit.
|
||||
|
||||
|
||||
### Step 3 summary - Build the coreboot toolchain.
|
||||
This builds one of the coreboot cross-compiler toolchains for X86 platforms.
|
||||
Because of the variability of compilers and the other required tools between
|
||||
the various operating systems that coreboot can be built on, coreboot supplies
|
||||
and uses its own cross-compiler toolchain to build the binaries that end up as
|
||||
part of the coreboot ROM. The toolchain provided by the operating system (the
|
||||
'host toolchain') is used to build various tools that will run on the local
|
||||
system during the build process.
|
||||
|
||||
This builds one of the coreboot cross-compiler toolchains for X86
|
||||
platforms. Because of the variability of compilers and the other
|
||||
required tools between the various operating systems that coreboot can
|
||||
be built on, coreboot supplies and uses its own cross-compiler toolchain
|
||||
to build the binaries that end up as part of the coreboot ROM. The
|
||||
toolchain provided by the operating system (the 'host toolchain') is
|
||||
used to build various tools that will run on the local system during the
|
||||
build process.
|
||||
|
||||
|
||||
### Step 4 summary - Build the payload
|
||||
|
||||
To actually do anything useful with coreboot, you need to build a payload to
|
||||
include into the rom. The idea behind coreboot is that it does the minimum amount
|
||||
possible before passing control of the machine to a payload. There are various
|
||||
payloads such as grub or SeaBIOS that are typically used to boot the operating
|
||||
system. Instead, we used coreinfo, a small demonstration payload that allows the
|
||||
user to look at various things such as memory and the contents of the coreboot
|
||||
file system (CBFS) - the pieces that make up the coreboot rom.
|
||||
To actually do anything useful with coreboot, you need to build a
|
||||
payload to include into the rom. The idea behind coreboot is that it
|
||||
does the minimum amount possible before passing control of the machine
|
||||
to a payload. There are various payloads such as grub or SeaBIOS that
|
||||
are typically used to boot the operating system. Instead, we used
|
||||
coreinfo, a small demonstration payload that allows the user to look at
|
||||
various things such as memory and the contents of the coreboot file
|
||||
system (CBFS) - the pieces that make up the coreboot rom.
|
||||
|
||||
|
||||
### Step 5 summary - Configure the build
|
||||
|
||||
This step configures coreboot's build options using the menuconfig interface to
|
||||
Kconfig. Kconfig is the same configuration program used by the linux kernel. It
|
||||
allows you to enable, disable, and change various values to control the coreboot
|
||||
build process, including which mainboard(motherboard) to use, which toolchain to
|
||||
use, and how the runtime debug console should be presented and saved.
|
||||
Anytime you change mainboards in Kconfig, you should always run `make distclean`
|
||||
before running `make menuconfig`. Due to the way that Kconfig works, values will
|
||||
be kept from the previous mainboard if you skip the clean step. This leads to a
|
||||
hybrid configuration which may or may not work as expected.
|
||||
This step configures coreboot's build options using the menuconfig
|
||||
interface to Kconfig. Kconfig is the same configuration program used by
|
||||
the linux kernel. It allows you to enable, disable, and change various
|
||||
values to control the coreboot build process, including which
|
||||
mainboard(motherboard) to use, which toolchain to use, and how the
|
||||
runtime debug console should be presented and saved. Anytime you change
|
||||
mainboards in Kconfig, you should always run `make distclean` before
|
||||
running `make menuconfig`. Due to the way that Kconfig works, values
|
||||
will be kept from the previous mainboard if you skip the clean step.
|
||||
This leads to a hybrid configuration which may or may not work as
|
||||
expected.
|
||||
|
||||
|
||||
### Step 6 summary - Build coreboot
|
||||
|
||||
You may notice that a number of other pieces are downloaded at the beginning of
|
||||
the build process. These are the git submodules used in various coreboot builds.
|
||||
By default, the _blobs_ submodule is not downloaded. This git submodule may be
|
||||
required for other builds for microcode or other binaries. To enable downloading
|
||||
this submodule, select the option "Allow use of binary-only repository" in the
|
||||
"General Setup" menu of Kconfig
|
||||
This attempts to build the coreboot rom. The rom file itself ends up in the
|
||||
build directory as 'coreboot.rom'. At the end of the build process, the build
|
||||
displayed the contents of the rom file.
|
||||
You may notice that a number of other pieces are downloaded at the
|
||||
beginning of the build process. These are the git submodules used in
|
||||
various coreboot builds. By default, the _blobs_ submodule is not
|
||||
downloaded. This git submodule may be required for other builds for
|
||||
microcode or other binaries. To enable downloading this submodule,
|
||||
select the option "Allow use of binary-only repository" in the "General
|
||||
Setup" menu of Kconfig This attempts to build the coreboot rom. The rom
|
||||
file itself ends up in the build directory as 'coreboot.rom'. At the end
|
||||
of the build process, the build displayed the contents of the rom file.
|
||||
|
||||
|
||||
### Step 7 summary - Install QEMU
|
||||
|
@ -253,11 +261,11 @@ process in a virtualised environment.
|
|||
|
||||
Here's the command line instruction broken down:
|
||||
* `qemu-system-x86_64`
|
||||
This starts the QEMU emulator with the i440FX host PCI bridge and PIIX3 PCI to
|
||||
ISA bridge.
|
||||
This starts the QEMU emulator with the i440FX host PCI bridge and PIIX3
|
||||
PCI to ISA bridge.
|
||||
* `-bios build/coreboot.rom`
|
||||
Use the coreboot rom image that we just built. If this flag is left out, the
|
||||
standard SeaBIOS image that comes with QEMU is used.
|
||||
Use the coreboot rom image that we just built. If this flag is left out,
|
||||
the standard SeaBIOS image that comes with QEMU is used.
|
||||
* `-serial stdio`
|
||||
Send the serial output to the console. This allows you to view the coreboot
|
||||
boot log.
|
||||
Send the serial output to the console. This allows you to view the
|
||||
coreboot boot log.
|
||||
|
|
|
@ -4,28 +4,29 @@
|
|||
|
||||
If you already have an account, skip to Step 2.
|
||||
|
||||
Otherwise, go to <https://review.coreboot.org> in your preferred web browser.
|
||||
Select **Sign in** in the upper right corner.
|
||||
Otherwise, go to <https://review.coreboot.org> in your preferred web
|
||||
browser. Select **Sign in** in the upper right corner.
|
||||
|
||||
Select the appropriate sign-in. For example, if you have a Google account,
|
||||
select **Google OAuth2** (gerrit-oauth-provider plugin). **Note:** Your
|
||||
username for the account will be the username of the account you used to
|
||||
sign-in with. (ex. your Google username).
|
||||
Select the appropriate sign-in. For example, if you have a Google
|
||||
account, select **Google OAuth2** (gerrit-oauth-provider plugin).
|
||||
**Note:** Your username for the account will be the username of the
|
||||
account you used to sign-in with. (ex. your Google username).
|
||||
|
||||
## Step 2a: Set up SSH keys
|
||||
|
||||
If you prefer to use an HTTP password instead, skip to Step 2b.
|
||||
|
||||
If you do not have an SSH key set up on your account already (as is the case
|
||||
with a newly created account), follow the instructions below; otherwise,
|
||||
doing so could overwrite an existing key.
|
||||
If you do not have an SSH key set up on your account already (as is the
|
||||
case with a newly created account), follow the instructions below;
|
||||
otherwise, doing so could overwrite an existing key.
|
||||
|
||||
In a terminal, run `ssh-keygen -t ed25519` and confirm the default path
|
||||
`.ssh/id_ed25519`.
|
||||
|
||||
Make a passphrase -- remember this phrase. It will be needed whenever you use
|
||||
this public key. **Note:** You might want to use a short password, or
|
||||
forego the password altogether as you will be using it very often.
|
||||
Make a passphrase -- remember this phrase. It will be needed whenever
|
||||
you use this public key. **Note:** You might want to use a short
|
||||
password, or forego the password altogether as you will be using it very
|
||||
often.
|
||||
|
||||
Copy the content of `.ssh/id_ed25519.pub` (notice the ".pub" suffix
|
||||
as you need to send the public key) into the textbox "New SSH Key" at
|
||||
|
@ -33,17 +34,19 @@ https://review.coreboot.org/settings/#SSHKeys and save it.
|
|||
|
||||
## Step 2b: Set up an HTTP Password
|
||||
|
||||
Alternatively, instead of using SSH keys, you can use an HTTP password. To do so,
|
||||
after you select your name and click on **Settings** on the left-hand side, rather
|
||||
than selecting **SSH Public Keys**, select **HTTP Password**.
|
||||
Alternatively, instead of using SSH keys, you can use an HTTP password.
|
||||
To do so, after you select your name and click on **Settings** on the
|
||||
left-hand side, rather than selecting **SSH Public Keys**, select **HTTP
|
||||
Password**.
|
||||
|
||||
Click **Generate Password**. This should fill the "Password" box with a password. Copy
|
||||
the password, and add the following to your `$HOME/.netrc` file:
|
||||
Click **Generate Password**. This should fill the "Password" box with a
|
||||
password. Copy the password, and add the following to your
|
||||
`$HOME/.netrc` file:
|
||||
|
||||
machine review.coreboot.org login YourUserNameHere password YourPasswordHere
|
||||
|
||||
where YourUserNameHere is your username, and YourPasswordHere is the password you
|
||||
just generated.
|
||||
where YourUserNameHere is your username, and YourPasswordHere is the
|
||||
password you just generated.
|
||||
|
||||
If your system is behind a snooping HTTPS proxy, you might also have to
|
||||
make its SSL certificate known to curl, a system specific operation.
|
||||
|
@ -55,26 +58,28 @@ certificate verification in git:
|
|||
The `--global` argument sets it for all git transfers of your local
|
||||
user, `false` means not to validate the certificate.
|
||||
|
||||
If that still doesn't allow you to pull or push changes to the server, the
|
||||
proxy is likely tampering with the data stream, in which case there's nothing
|
||||
we can do.
|
||||
If that still doesn't allow you to pull or push changes to the server,
|
||||
the proxy is likely tampering with the data stream, in which case
|
||||
there's nothing we can do.
|
||||
|
||||
## Step 3: Clone coreboot and configure it for submitting patches
|
||||
|
||||
On Gerrit, click on the **Browse** tab in the upper left corner and select
|
||||
**Repositories**. From the listing, select the "coreboot" repo. You may have
|
||||
to click the next page arrow at the bottom a few times to find it.
|
||||
On Gerrit, click on the **Browse** tab in the upper left corner and
|
||||
select **Repositories**. From the listing, select the "coreboot" repo.
|
||||
You may have to click the next page arrow at the bottom a few times to
|
||||
find it.
|
||||
|
||||
If you are using SSH keys, select **ssh** from the tabs under "Project
|
||||
coreboot" and run the "clone with commit-msg hook" command that's provided.
|
||||
This should prompt you for your id_rsa passphrase, if you previously set one.
|
||||
coreboot" and run the "clone with commit-msg hook" command that's
|
||||
provided. This should prompt you for your id_rsa passphrase, if you
|
||||
previously set one.
|
||||
|
||||
**Note:** if the **ssh** option is not showing, check that you have a username
|
||||
set. Click the profile picture at the top right and select **User Settings**,
|
||||
then set your username in the **Profile** section.
|
||||
**Note:** if the **ssh** option is not showing, check that you have a
|
||||
username set. Click the profile picture at the top right and select
|
||||
**User Settings**, then set your username in the **Profile** section.
|
||||
|
||||
If you are using HTTP, instead, select **http** from the tabs under "Project coreboot"
|
||||
and run the command that appears.
|
||||
If you are using HTTP, instead, select **http** from the tabs under
|
||||
"Project coreboot" and run the command that appears.
|
||||
|
||||
Now is a good time to configure your global git identity, if you haven't
|
||||
already.
|
||||
|
@ -82,30 +87,32 @@ already.
|
|||
git config --global user.name "Your Name"
|
||||
git config --global user.email "Your Email"
|
||||
|
||||
Finally, enter the local git repository and set up repository specific hooks
|
||||
and other configurations.
|
||||
Finally, enter the local git repository and set up repository specific
|
||||
hooks and other configurations.
|
||||
|
||||
cd coreboot
|
||||
make gitconfig
|
||||
|
||||
## Step 4: Submit a commit
|
||||
|
||||
An easy first commit to make is fixing existing checkpatch errors and warnings
|
||||
in the source files. To see errors that are already present, build the files in
|
||||
the repository by running `make lint` in the coreboot directory. Alternatively,
|
||||
if you want to run `make lint` on a specific directory, run:
|
||||
An easy first commit to make is fixing existing checkpatch errors and
|
||||
warnings in the source files. To see errors that are already present,
|
||||
build the files in the repository by running `make lint` in the coreboot
|
||||
directory. Alternatively, if you want to run `make lint` on a specific
|
||||
directory, run:
|
||||
|
||||
util/lint/lint-007-checkpatch <filepath>
|
||||
|
||||
where `filepath` is the filepath of the directory (ex. `src/cpu/amd/car`).
|
||||
where `filepath` is the filepath of the directory (ex.
|
||||
`src/cpu/amd/car`).
|
||||
|
||||
Any changes made to files under the src directory are made locally,
|
||||
and can be submitted for review.
|
||||
|
||||
Once you finish making your desired changes, use the command line to stage
|
||||
and submit your changes. An alternative and potentially easier way to stage
|
||||
and submit commits is to use git cola, a graphical user interface for git. For
|
||||
instructions on how to do so, skip to Step 4b.
|
||||
Once you finish making your desired changes, use the command line to
|
||||
stage and submit your changes. An alternative and potentially easier way
|
||||
to stage and submit commits is to use git cola, a graphical user
|
||||
interface for git. For instructions on how to do so, skip to Step 4b.
|
||||
|
||||
## Step 4a: Use the command line to stage and submit a commit
|
||||
|
||||
|
@ -119,20 +126,21 @@ To commit the change, run
|
|||
|
||||
git commit -s
|
||||
|
||||
**Note:** The -s adds a signed-off-by line by the committer. Your commit should be
|
||||
signed off with your name and email (i.e. **Your Name** **\<Your Email\>**, based on
|
||||
what you set with git config earlier).
|
||||
**Note:** The -s adds a signed-off-by line by the committer. Your commit
|
||||
should be signed off with your name and email (i.e. **Your Name**
|
||||
**\<Your Email\>**, based on what you set with git config earlier).
|
||||
|
||||
Running git commit first checks for any errors and warnings using lint. If
|
||||
there are any, you must go back and fix them before submitting your commit.
|
||||
You can do so by making the necessary changes, and then staging your commit again.
|
||||
Running git commit first checks for any errors and warnings using lint.
|
||||
If there are any, you must go back and fix them before submitting your
|
||||
commit. You can do so by making the necessary changes, and then staging
|
||||
your commit again.
|
||||
|
||||
When there are no errors or warnings, your default text editor will open.
|
||||
This is where you will write your commit message.
|
||||
When there are no errors or warnings, your default text editor will
|
||||
open. This is where you will write your commit message.
|
||||
|
||||
The first line of your commit message is your commit summary. This is a brief
|
||||
one-line description of what you changed in the files using the template
|
||||
below:
|
||||
The first line of your commit message is your commit summary. This is a
|
||||
brief one-line description of what you changed in the files using the
|
||||
template below:
|
||||
|
||||
<filepath>: Short description
|
||||
|
||||
|
@ -143,29 +151,30 @@ For example,
|
|||
**Note:** It is good practice to use present tense in your descriptions
|
||||
and do not punctuate your summary.
|
||||
|
||||
Then hit Enter. The next paragraph should be a more in-depth explanation of the
|
||||
changes you've made to the files. Again, it is good practice to use present
|
||||
tense. Ex.
|
||||
Then hit Enter. The next paragraph should be a more in-depth explanation
|
||||
of the changes you've made to the files. Again, it is good practice to
|
||||
use present tense. Ex.
|
||||
|
||||
Fix space prohibited between function name and open parenthesis,
|
||||
line over 80 characters, unnecessary braces for single statement blocks,
|
||||
space required before open brace errors and warnings.
|
||||
line over 80 characters, unnecessary braces for single statement
|
||||
blocks, space required before open brace errors and warnings.
|
||||
|
||||
When you have finished writing your commit message, save and exit the text
|
||||
editor. You have finished committing your change. If, after submitting your
|
||||
commit, you wish to make changes to it, running `git commit --amend` allows
|
||||
you to take back your commit and amend it.
|
||||
When you have finished writing your commit message, save and exit the
|
||||
text editor. You have finished committing your change. If, after
|
||||
submitting your commit, you wish to make changes to it, running `git
|
||||
commit --amend` allows you to take back your commit and amend it.
|
||||
|
||||
When you are done with your commit, run `git push` to push your commit to
|
||||
coreboot.org. **Note:** To submit as a private patch, use
|
||||
`git push origin HEAD:refs/for/master%private`. Submitting as a private patch
|
||||
means that your commit will be on review.coreboot.org, but is only visible to
|
||||
yourself and those you add as reviewers. This mode isn't perfect: Somebody who
|
||||
knows the commit ID can still fetch the change and everything it refers (e.g.
|
||||
parent commits).
|
||||
When you are done with your commit, run `git push` to push your commit
|
||||
to coreboot.org. **Note:** To submit as a private patch, use `git push
|
||||
origin HEAD:refs/for/master%private`. Submitting as a private patch
|
||||
means that your commit will be on review.coreboot.org, but is only
|
||||
visible to yourself and those you add as reviewers. This mode isn't
|
||||
perfect: Somebody who knows the commit ID can still fetch the change and
|
||||
everything it refers (e.g. parent commits).
|
||||
|
||||
This has been a quick primer on how to submit a change to Gerrit for review
|
||||
using git. You may wish to review the [Gerrit code review workflow
|
||||
This has been a quick primer on how to submit a change to Gerrit for
|
||||
review using git. You may wish to review the [Gerrit code review
|
||||
workflow
|
||||
documentation](https://gerrit-review.googlesource.com/Documentation/intro-user.html#code-review),
|
||||
especially if you plan to work on multiple changes at the same time.
|
||||
|
||||
|
@ -196,14 +205,14 @@ in-depth explanation of the changes you've made to the files. Again, it
|
|||
is good practice to use present tense. Ex.
|
||||
|
||||
Fix space prohibited between function name and open parenthesis,
|
||||
line over 80 characters, unnecessary braces for single statement blocks,
|
||||
space required before open brace errors and warnings.
|
||||
line over 80 characters, unnecessary braces for single statement
|
||||
blocks, space required before open brace errors and warnings.
|
||||
|
||||
Then press Enter two times to move the cursor to below your description.
|
||||
To the left of the text boxes, there is an icon with an downward arrow.
|
||||
Press the arrow and select "Sign Off." Make sure that you are signing off
|
||||
with your name and email (i.e. **Your Name** **\<Your Email\>**, based on what
|
||||
you set with git config earlier).
|
||||
Press the arrow and select "Sign Off." Make sure that you are signing
|
||||
off with your name and email (i.e. **Your Name** **\<Your Email\>**,
|
||||
based on what you set with git config earlier).
|
||||
|
||||
Now, review each of your changes and mark either individual changes or
|
||||
an entire file as Ready to Commit by marking it as 'Staged'. To do
|
||||
|
@ -234,11 +243,11 @@ and the commit succeeds, move to the command line and run `git push`.
|
|||
|
||||
Your commits can now be seen on review.coreboot.org if you select "Your"
|
||||
and click on "Changes" and can be reviewed by others. Your code will
|
||||
first be reviewed by build bot (Jenkins), which will either give you a warning
|
||||
or verify a successful build; if so, your commit will receive a +1. Other
|
||||
users may also give your commit +1. For a commit to be merged, it needs
|
||||
to receive a +2. **Note:** A +1 and a +1 does not make a +2. Only certain users
|
||||
can give a +2.
|
||||
first be reviewed by build bot (Jenkins), which will either give you a
|
||||
warning or verify a successful build; if so, your commit will receive a
|
||||
+1. Other users may also give your commit +1. For a commit to be merged,
|
||||
it needs to receive a +2. **Note:** A +1 and a +1 does not make a +2.
|
||||
Only certain users can give a +2.
|
||||
|
||||
## Step 6 (optional): bash-git-prompt
|
||||
|
||||
|
@ -255,9 +264,11 @@ as this one is specific to bash.
|
|||
Alternatively, follow the instructions below:
|
||||
Run the following two commands in the command line:
|
||||
|
||||
cd
|
||||
git clone https://github.com/magicmonty/bash-git-prompt.git .bash-git-prompt --depth=1
|
||||
|
||||
```Bash
|
||||
cd
|
||||
git clone https://github.com/magicmonty/bash-git-prompt.git \
|
||||
.bash-git-prompt --depth=1
|
||||
```
|
||||
**Note:** cd will change your directory to your home directory, so the
|
||||
git clone command will be run there.
|
||||
|
||||
|
@ -269,36 +280,38 @@ Finally, open the `~/.bashrc` file and append the following two lines:
|
|||
Now, whenever you are in a git repository, it will continuously display
|
||||
its state.
|
||||
|
||||
There also are additional configurations that you can change depending on your
|
||||
preferences. If you wish to do so, look at the "All configs for .bashrc" section
|
||||
on <https://github.com/magicmonty/bash-git-prompt>. Listed in that section are
|
||||
various lines that you can copy, uncomment and add to your .bashrc file to
|
||||
change the configurations. Example configurations include avoid fetching remote
|
||||
status, and supporting versions of Git older than 1.7.10.
|
||||
There also are additional configurations that you can change depending
|
||||
on your preferences. If you wish to do so, look at the "All configs for
|
||||
.bashrc" section on <https://github.com/magicmonty/bash-git-prompt>.
|
||||
Listed in that section are various lines that you can copy, uncomment
|
||||
and add to your .bashrc file to change the configurations. Example
|
||||
configurations include avoid fetching remote status, and supporting
|
||||
versions of Git older than 1.7.10.
|
||||
|
||||
## Appendix: Miscellaneous Advice
|
||||
|
||||
### Updating a commit after running git push:
|
||||
|
||||
Suppose you would like to update a commit that has already been pushed to the
|
||||
remote repository. If the commit you wish to update is the most recent
|
||||
commit you have made, after making your desired changes, stage the files
|
||||
(either using git add or in git cola), and amend the commit. To do so,
|
||||
if you are using the command line, run `git commit --amend`. If you are
|
||||
using git cola, click on the gear icon located on the upper left side under
|
||||
**Commit** and select **Amend Last Commit** in the drop down menu. Then, stage
|
||||
the files you have changed, commit the changes, and run git push to push the
|
||||
changes to the remote repository. Your change should be reflected in Gerrit as
|
||||
a new patch set.
|
||||
Suppose you would like to update a commit that has already been pushed
|
||||
to the remote repository. If the commit you wish to update is the most
|
||||
recent commit you have made, after making your desired changes, stage
|
||||
the files (either using git add or in git cola), and amend the commit.
|
||||
To do so, if you are using the command line, run `git commit --amend`.
|
||||
If you are using git cola, click on the gear icon located on the upper
|
||||
left side under **Commit** and select **Amend Last Commit** in the drop
|
||||
down menu. Then, stage the files you have changed, commit the changes,
|
||||
and run git push to push the changes to the remote repository. Your
|
||||
change should be reflected in Gerrit as a new patch set.
|
||||
|
||||
If, however, the commit you wish to update is not the most recent commit you
|
||||
have made, you will first need to checkout that commit. To do so, find the
|
||||
URL of the commit on <https://review.coreboot.org> and go to that page; if
|
||||
the commit is one that you previously pushed, it can be found by selecting
|
||||
**My** and then **Changes** in the upper left corner. To checkout this commit,
|
||||
in the upper right corner, click on **Download**, and copy the command listed
|
||||
next to checkout by clicking **Copy to clipboard**. Then, run the copied
|
||||
command in your coreboot repository. Now, the last commit should be the most
|
||||
recent commit to that patch; to update it, make your desired changes, stage
|
||||
the files, then amend and push the commit using the instructions in the above
|
||||
If, however, the commit you wish to update is not the most recent commit
|
||||
you have made, you will first need to checkout that commit. To do so,
|
||||
find the URL of the commit on <https://review.coreboot.org> and go to
|
||||
that page; if the commit is one that you previously pushed, it can be
|
||||
found by selecting **My** and then **Changes** in the upper left corner.
|
||||
To checkout this commit, in the upper right corner, click on
|
||||
**Download**, and copy the command listed next to checkout by clicking
|
||||
**Copy to clipboard**. Then, run the copied command in your coreboot
|
||||
repository. Now, the last commit should be the most recent commit to
|
||||
that patch; to update it, make your desired changes, stage the files,
|
||||
then amend and push the commit using the instructions in the above
|
||||
paragraph.
|
||||
|
|
|
@ -1,31 +1,32 @@
|
|||
# Writing unit tests for coreboot
|
||||
|
||||
## Introduction
|
||||
General thoughts about unit testing coreboot can be found in
|
||||
[Unit testing coreboot](../technotes/2020-03-unit-testing-coreboot.md).
|
||||
Additionally, [code coverage](../technotes/2021-05-code-coverage.md) support
|
||||
is available for unit tests.
|
||||
General thoughts about unit testing coreboot can be found in [Unit
|
||||
testing coreboot](../technotes/2020-03-unit-testing-coreboot.md).
|
||||
Additionally, [code coverage](../technotes/2021-05-code-coverage.md)
|
||||
support is available for unit tests.
|
||||
|
||||
This document aims to guide developers through the process of adding and writing
|
||||
unit tests for coreboot modules.
|
||||
This document aims to guide developers through the process of adding and
|
||||
writing unit tests for coreboot modules.
|
||||
|
||||
As an example of unit under test, `src/device/i2c.c` (referred hereafter as UUT
|
||||
"Unit Under Test") will be used. This is simple module, thus it should be easy
|
||||
for the reader to focus solely on the testing logic, without the need to spend
|
||||
too much time on digging deeply into the source code details and flow of
|
||||
operations. That being said, a good understanding of what the unit under test is
|
||||
doing is crucial for writing unit tests.
|
||||
As an example of unit under test, `src/device/i2c.c` (referred hereafter
|
||||
as UUT "Unit Under Test") will be used. This is simple module, thus it
|
||||
should be easy for the reader to focus solely on the testing logic,
|
||||
without the need to spend too much time on digging deeply into the
|
||||
source code details and flow of operations. That being said, a good
|
||||
understanding of what the unit under test is doing is crucial for
|
||||
writing unit tests.
|
||||
|
||||
This tutorial should also be helpful for developers who want to follow
|
||||
[TDD](https://en.wikipedia.org/wiki/Test-driven_development). Even though TDD
|
||||
has a different work flow of building tests first, followed by the code that
|
||||
satisfies them, the process of writing tests and adding them to the tree is the
|
||||
same.
|
||||
[TDD](https://en.wikipedia.org/wiki/Test-driven_development). Even
|
||||
though TDD has a different work flow of building tests first, followed
|
||||
by the code that satisfies them, the process of writing tests and adding
|
||||
them to the tree is the same.
|
||||
|
||||
## Analysis of unit under test
|
||||
First of all, it is necessary to precisely establish what we want to test in a
|
||||
particular module. Usually this will be an externally exposed API, which can be
|
||||
used by other modules.
|
||||
## Analysis of unit under test First of all, it is necessary to
|
||||
precisely establish what we want to test in a particular module. Usually
|
||||
this will be an externally exposed API, which can be used by other
|
||||
modules.
|
||||
|
||||
```eval_rst
|
||||
.. admonition:: i2c-test example
|
||||
|
@ -34,66 +35,70 @@ used by other modules.
|
|||
|
||||
.. code-block:: c
|
||||
|
||||
int i2c_read_field(unsigned int bus, uint8_t chip, uint8_t reg, uint8_t *data,
|
||||
uint8_t mask, uint8_t shift)
|
||||
int i2c_write_field(unsigned int bus, uint8_t chip, uint8_t reg, uint8_t data,
|
||||
uint8_t mask, uint8_t shift)
|
||||
int i2c_read_field(unsigned int bus, uint8_t chip, uint8_t reg,
|
||||
uint8_t *data, uint8_t mask, uint8_t shift)
|
||||
int i2c_write_field(unsigned int bus, uint8_t chip, uint8_t reg,
|
||||
uint8_t data, uint8_t mask, uint8_t shift)
|
||||
|
||||
For sake of simplicity, let's focus on `i2c_read_field` in this document.
|
||||
For sake of simplicity, let's focus on `i2c_read_field` in this
|
||||
document.
|
||||
```
|
||||
|
||||
Once the API is defined, the next question is __what__ this API is doing (or
|
||||
what it will be doing in case of TDD). In other words, what outputs we are
|
||||
expecting from particular functions, when providing particular input parameters.
|
||||
Once the API is defined, the next question is __what__ this API is doing
|
||||
(or what it will be doing in case of TDD). In other words, what outputs
|
||||
we are expecting from particular functions, when providing particular
|
||||
input parameters.
|
||||
|
||||
```eval_rst
|
||||
.. admonition:: i2c-test example
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
int i2c_read_field(unsigned int bus, uint8_t chip, uint8_t reg, uint8_t *data,
|
||||
uint8_t mask, uint8_t shift)
|
||||
int i2c_read_field(unsigned int bus, uint8_t chip, uint8_t reg,
|
||||
uint8_t *data, uint8_t mask, uint8_t shift)
|
||||
|
||||
This is a method which means to read content of register `reg` from i2c device
|
||||
on i2c `bus` and slave address `chip`, applying bit `mask` and offset `shift`
|
||||
to it. Returned data should be placed in `data`.
|
||||
This is a method which means to read content of register `reg` from
|
||||
i2c device on i2c `bus` and slave address `chip`, applying bit `mask`
|
||||
and offset `shift` to it. Returned data should be placed in `data`.
|
||||
```
|
||||
|
||||
The next step is to determine all external dependencies of UUT in order to mock
|
||||
them out. Usually we want to isolate the UUT as much as possible, so that the
|
||||
test result depends __only__ on the behavior of UUT and not on the other
|
||||
modules. While some software dependencies may be hard to be mock (for example
|
||||
due to complicated dependencies) and thus should be simply linked into the test
|
||||
binaries, all hardware dependencies need to be mocked out, since in the
|
||||
user-space host environment, targets hardware is not available.
|
||||
The next step is to determine all external dependencies of UUT in order
|
||||
to mock them out. Usually we want to isolate the UUT as much as
|
||||
possible, so that the test result depends __only__ on the behavior of
|
||||
UUT and not on the other modules. While some software dependencies may
|
||||
be hard to be mock (for example due to complicated dependencies) and
|
||||
thus should be simply linked into the test binaries, all hardware
|
||||
dependencies need to be mocked out, since in the user-space host
|
||||
environment, targets hardware is not available.
|
||||
|
||||
```eval_rst
|
||||
.. admonition:: i2c-test example
|
||||
|
||||
`i2c_read_field` is calling `i2c_readb`, which eventually invokes
|
||||
`i2c_transfer`. This method simply calls `platform_i2c_transfer`. The last
|
||||
function in the chain is a hardware-touching one, and defined separately for
|
||||
different SOCs. It is responsible for issuing transactions on the i2c bus.
|
||||
For the purpose of writing unit test, we should mock this function.
|
||||
`i2c_transfer`. This method simply calls `platform_i2c_transfer`. The
|
||||
last function in the chain is a hardware-touching one, and defined
|
||||
separately for different SOCs. It is responsible for issuing
|
||||
transactions on the i2c bus. For the purpose of writing unit test,
|
||||
we should mock this function.
|
||||
```
|
||||
|
||||
## Adding new tests
|
||||
In order to keep the tree clean, the `tests/` directory should mimic the `src/`
|
||||
directory, so that test harness code is placed in a location corresponding to
|
||||
UUT. Furthermore, the naming convention is to add the suffix `-test` to the UUT
|
||||
name when creating a new test harness file.
|
||||
In order to keep the tree clean, the `tests/` directory should mimic the
|
||||
`src/` directory, so that test harness code is placed in a location
|
||||
corresponding to UUT. Furthermore, the naming convention is to add the
|
||||
suffix `-test` to the UUT name when creating a new test harness file.
|
||||
|
||||
```eval_rst
|
||||
.. admonition:: i2c-test example
|
||||
|
||||
Considering that UUT is `src/device/i2c.c`, test file should be named
|
||||
`tests/device/i2c-test.c`. When adding a new test file, it needs to be
|
||||
registered with the coreboot unit testing infrastructure.
|
||||
`tests/device/i2c-test.c`. When adding a new test file, it needs to
|
||||
be registered with the coreboot unit testing infrastructure.
|
||||
```
|
||||
|
||||
Every directory under `tests/` should contain a Makefile.inc, similar to what
|
||||
can be seen under the `src/`. Register a new test in Makefile.inc, by
|
||||
__appending__ test name to the `tests-y` variable.
|
||||
Every directory under `tests/` should contain a Makefile.inc, similar to
|
||||
what can be seen under the `src/`. Register a new test in Makefile.inc,
|
||||
by __appending__ test name to the `tests-y` variable.
|
||||
|
||||
```eval_rst
|
||||
.. admonition:: i2c-test example
|
||||
|
@ -103,10 +108,11 @@ __appending__ test name to the `tests-y` variable.
|
|||
tests-y += i2c-test
|
||||
```
|
||||
|
||||
Next step is to list all source files, which should be linked together in order
|
||||
to create test binary. Usually a tests requires only two files - UUT and test
|
||||
harness code, but sometimes more is needed to provide the test environment.
|
||||
Source files are registered in `<test_name>-srcs` variable.
|
||||
Next step is to list all source files, which should be linked together
|
||||
in order to create test binary. Usually a tests requires only two files
|
||||
- UUT and test harness code, but sometimes more is needed to provide the
|
||||
test environment. Source files are registered in `<test_name>-srcs`
|
||||
variable.
|
||||
|
||||
```eval_rst
|
||||
.. admonition:: i2c-test example
|
||||
|
@ -117,9 +123,10 @@ Source files are registered in `<test_name>-srcs` variable.
|
|||
i2c-test-srcs += src/device/i2c.c
|
||||
```
|
||||
|
||||
Above minimal configuration is a basis for further work. One can try to build
|
||||
and run test binary either by invoking `make tests/<test_dir>/<test_name>` or by
|
||||
running all unit tests (whole suite) for coreboot `make unit-tests`.
|
||||
Above minimal configuration is a basis for further work. One can try to
|
||||
build and run test binary either by invoking `make
|
||||
tests/<test_dir>/<test_name>` or by running all unit tests (whole suite)
|
||||
for coreboot `make unit-tests`.
|
||||
|
||||
```eval_rst
|
||||
.. admonition:: i2c-test example
|
||||
|
@ -135,31 +142,34 @@ running all unit tests (whole suite) for coreboot `make unit-tests`.
|
|||
make unit-tests
|
||||
```
|
||||
|
||||
When trying to build test binary, one can often see linker complains about
|
||||
`undefined reference` to couple of symbols. This is one of solutions to
|
||||
determine all external dependencies of UUT - iteratively build test and resolve
|
||||
errors one by one. At this step, developer should decide either it's better to
|
||||
add an extra module to provide necessary definitions or rather mock such
|
||||
dependency. Quick guide through adding mocks is provided later in this doc.
|
||||
When trying to build test binary, one can often see linker complains
|
||||
about `undefined reference` to couple of symbols. This is one of
|
||||
solutions to determine all external dependencies of UUT - iteratively
|
||||
build test and resolve errors one by one. At this step, developer should
|
||||
decide either it's better to add an extra module to provide necessary
|
||||
definitions or rather mock such dependency. Quick guide through adding
|
||||
mocks is provided later in this doc.
|
||||
|
||||
## Writing new tests
|
||||
In coreboot, [Cmocka](https://cmocka.org/) is used as unit test framework. The
|
||||
project has exhaustive [API documentation](https://api.cmocka.org/). Let's see
|
||||
how we may incorporate it when writing tests.
|
||||
In coreboot, [Cmocka](https://cmocka.org/) is used as unit test
|
||||
framework. The project has exhaustive [API
|
||||
documentation](https://api.cmocka.org/). Let's see how we may
|
||||
incorporate it when writing tests.
|
||||
|
||||
### Assertions
|
||||
Testing the UUT consists of calling the functions in the UUT and comparing the
|
||||
returned values to the expected values. Cmocka implements
|
||||
[a set of assert macros](https://api.cmocka.org/group__cmocka__asserts.html) to
|
||||
compare a value with an expected value. If the two values do not match, the test
|
||||
Testing the UUT consists of calling the functions in the UUT and
|
||||
comparing the returned values to the expected values. Cmocka implements
|
||||
[a set of assert
|
||||
macros](https://api.cmocka.org/group__cmocka__asserts.html) to compare a
|
||||
value with an expected value. If the two values do not match, the test
|
||||
fails with an error message.
|
||||
|
||||
```eval_rst
|
||||
.. admonition:: i2c-test example
|
||||
|
||||
In our example, the simplest test is to call UUT for reading our fake devices
|
||||
registers and do all calculation in the test harness itself. At the end, let's
|
||||
compare integers with `assert_int_equal`.
|
||||
In our example, the simplest test is to call UUT for reading our fake
|
||||
devices registers and do all calculation in the test harness itself.
|
||||
At the end, let's compare integers with `assert_int_equal`.
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
|
@ -191,24 +201,25 @@ fails with an error message.
|
|||
### Mocks
|
||||
|
||||
#### Overview
|
||||
Many coreboot modules are low level software that touch hardware directly.
|
||||
Because of this, one of the most important and challenging part of
|
||||
writing tests is to design and implement mocks. A mock is a software component
|
||||
which implements the API of another component so that the test can verify that
|
||||
certain functions are called (or not called), verify the parameters passed to
|
||||
those functions, and specify the return values from those functions. Mocks are
|
||||
especially useful when the API to be implemented is one that accesses hardware
|
||||
components.
|
||||
Many coreboot modules are low level software that touch hardware
|
||||
directly. Because of this, one of the most important and challenging
|
||||
part of writing tests is to design and implement mocks. A mock is a
|
||||
software component which implements the API of another component so that
|
||||
the test can verify that certain functions are called (or not called),
|
||||
verify the parameters passed to those functions, and specify the return
|
||||
values from those functions. Mocks are especially useful when the API to
|
||||
be implemented is one that accesses hardware components.
|
||||
|
||||
When writing a mock, the developer implements the same API as the module being
|
||||
mocked. Such a mock may, for example, register a set of driver methods. Behind
|
||||
this API, there is usually a simulation of real hardware.
|
||||
When writing a mock, the developer implements the same API as the module
|
||||
being mocked. Such a mock may, for example, register a set of driver
|
||||
methods. Behind this API, there is usually a simulation of real
|
||||
hardware.
|
||||
|
||||
```eval_rst
|
||||
.. admonition:: i2c-test example
|
||||
|
||||
For purpose of our i2c test, we may introduce two i2c devices with set of
|
||||
registers, which simply are structs in memory.
|
||||
For purpose of our i2c test, we may introduce two i2c devices with
|
||||
set of registers, which simply are structs in memory.
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
|
@ -266,16 +277,17 @@ this API, there is usually a simulation of real hardware.
|
|||
};
|
||||
```
|
||||
|
||||
Cmocka uses a feature that gcc provides for breaking dependencies at the link
|
||||
time. It is possible to override implementation of some function, with the
|
||||
method from test harness. This allows test harness to take control of execution
|
||||
from binary (during the execution of test), and stimulate UUT as required
|
||||
without changing the source code.
|
||||
Cmocka uses a feature that gcc provides for breaking dependencies at the
|
||||
link time. It is possible to override implementation of some function,
|
||||
with the method from test harness. This allows test harness to take
|
||||
control of execution from binary (during the execution of test), and
|
||||
stimulate UUT as required without changing the source code.
|
||||
|
||||
coreboot unit test infrastructure supports overriding of functions at link time.
|
||||
This is as simple as adding a `name_of_function` to be mocked into
|
||||
<test_name>-mocks variable in Makefile.inc. The result is that the test's
|
||||
implementation of that function is called instead of coreboot's.
|
||||
coreboot unit test infrastructure supports overriding of functions at
|
||||
link time. This is as simple as adding a `name_of_function` to be
|
||||
mocked into <test_name>-mocks variable in Makefile.inc. The result is
|
||||
that the test's implementation of that function is called instead of
|
||||
coreboot's.
|
||||
|
||||
```eval_rst
|
||||
.. admonition:: i2c-test example
|
||||
|
@ -284,44 +296,45 @@ implementation of that function is called instead of coreboot's.
|
|||
|
||||
i2c-test-mocks += platform_i2c_transfer
|
||||
|
||||
Now, dev can write own implementation of `platform_i2c_transfer`. This
|
||||
implementation instead of accessing real i2c bus, will write/read from
|
||||
fake structs.
|
||||
Now, dev can write own implementation of `platform_i2c_transfer`.
|
||||
This implementation instead of accessing real i2c bus, will
|
||||
write/read from fake structs.
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
int platform_i2c_transfer(unsigned int bus, struct i2c_msg *segments,
|
||||
int count)
|
||||
int platform_i2c_transfer(unsigned int bus, struct i2c_msg
|
||||
*segments, int count)
|
||||
{
|
||||
}
|
||||
```
|
||||
|
||||
#### Checking mock's arguments
|
||||
A test can verify the parameters provided by the UUT to the mock function. The
|
||||
developer may also verify that number of calls to mock is correct and the order
|
||||
of calls to particular mocks is as expected (See
|
||||
[this](https://api.cmocka.org/group__cmocka__call__order.html)). The Cmocka
|
||||
macros for checking parameters are described
|
||||
[here](https://api.cmocka.org/group__cmocka__param.html). In general, in mock
|
||||
function, one makes a call to `check_expected(<param_name>)` and in the
|
||||
corresponding test function, `expect*()` macro, with description which parameter
|
||||
in which mock should have particular value, or be inside a described range.
|
||||
A test can verify the parameters provided by the UUT to the mock
|
||||
function. The developer may also verify that number of calls to mock is
|
||||
correct and the order of calls to particular mocks is as expected (See
|
||||
[this](https://api.cmocka.org/group__cmocka__call__order.html)). The
|
||||
Cmocka macros for checking parameters are described
|
||||
[here](https://api.cmocka.org/group__cmocka__param.html). In general, in
|
||||
mock function, one makes a call to `check_expected(<param_name>)` and in
|
||||
the corresponding test function, `expect*()` macro, with description
|
||||
which parameter in which mock should have particular value, or be inside
|
||||
a described range.
|
||||
|
||||
```eval_rst
|
||||
.. admonition:: i2c-test example
|
||||
|
||||
In our example, we may want to check that `platform_i2c_transfer` is fed with
|
||||
number of segments bigger than 0, each segment has flags which are in
|
||||
supported range and each segment has buf which is non-NULL. We are expecting
|
||||
such values for _every_ call, thus the last parameter in `expect*` macros is
|
||||
-1.
|
||||
In our example, we may want to check that `platform_i2c_transfer` is
|
||||
fed with number of segments bigger than 0, each segment has flags
|
||||
which are in supported range and each segment has buf which is
|
||||
non-NULL. We are expecting such values for _every_ call, thus the
|
||||
last parameter in `expect*` macros is -1.
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
static void mock_expect_params_platform_i2c_transfer(void)
|
||||
{
|
||||
unsigned long int expected_flags[] = {0, I2C_M_RD, I2C_M_TEN,
|
||||
I2C_M_RECV_LEN, I2C_M_NOSTART};
|
||||
unsigned long int expected_flags[] = {0, I2C_M_RD,
|
||||
I2C_M_TEN, I2C_M_RECV_LEN, I2C_M_NOSTART};
|
||||
|
||||
/* Flags should always be only within supported range */
|
||||
expect_in_set_count(platform_i2c_transfer, segments->flags,
|
||||
|
@ -330,8 +343,8 @@ in which mock should have particular value, or be inside a described range.
|
|||
expect_not_value_count(platform_i2c_transfer, segments->buf,
|
||||
NULL, -1);
|
||||
|
||||
expect_in_range_count(platform_i2c_transfer, count, 1, INT_MAX,
|
||||
-1);
|
||||
expect_in_range_count(platform_i2c_transfer, count, 1,
|
||||
INT_MAX, -1);
|
||||
}
|
||||
|
||||
And the checks below should be added to our mock
|
||||
|
@ -347,11 +360,11 @@ in which mock should have particular value, or be inside a described range.
|
|||
```
|
||||
|
||||
#### Instrument mocks
|
||||
It is possible for the test function to instrument what the mock will return to
|
||||
the UUT. This can be done by using the `will_return*()` and `mock()` macros.
|
||||
These are described in
|
||||
[the Mock Object section](https://api.cmocka.org/group__cmocka__mock.html) of
|
||||
the Cmocka API documentation.
|
||||
It is possible for the test function to instrument what the mock will
|
||||
return to the UUT. This can be done by using the `will_return*()` and
|
||||
`mock()` macros. These are described in [the Mock Object
|
||||
section](https://api.cmocka.org/group__cmocka__mock.html) of the Cmocka
|
||||
API documentation.
|
||||
|
||||
```eval_rst
|
||||
.. admonition:: Example
|
||||
|
@ -361,17 +374,18 @@ the Cmocka API documentation.
|
|||
```
|
||||
|
||||
### Test runner
|
||||
Finally, the developer needs to implement the test `main()` function. All tests
|
||||
should be registered there and cmocka test runner invoked. All methods for
|
||||
invoking Cmocka test are described
|
||||
Finally, the developer needs to implement the test `main()` function.
|
||||
All tests should be registered there and cmocka test runner invoked. All
|
||||
methods for invoking Cmocka test are described
|
||||
[here](https://api.cmocka.org/group__cmocka__exec.html).
|
||||
|
||||
```eval_rst
|
||||
.. admonition:: i2c-test example
|
||||
|
||||
We don't need any extra setup and teardown functions for i2c-test, so let's
|
||||
simply register test for `i2c_read_field` and return from main value which is
|
||||
output of Cmocka's runner (it returns number of tests that failed).
|
||||
We don't need any extra setup and teardown functions for i2c-test, so
|
||||
let's simply register test for `i2c_read_field` and return from main
|
||||
value which is output of Cmocka's runner (it returns number of tests
|
||||
that failed).
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
|
|
Loading…
Reference in New Issue