mirror of
https://github.com/libgit2/libgit2.git
synced 2026-06-22 06:26:26 +00:00
89
.travis.yml
89
.travis.yml
@@ -1,89 +0,0 @@
|
||||
# Travis-CI Build for libgit2
|
||||
# see travis-ci.org for details
|
||||
|
||||
language: c
|
||||
|
||||
os:
|
||||
- linux
|
||||
- osx
|
||||
|
||||
compiler:
|
||||
- gcc
|
||||
- clang
|
||||
|
||||
# Settings to try
|
||||
env:
|
||||
global:
|
||||
- secure: "YnhS+8n6B+uoyaYfaJ3Lei7cSJqHDPiKJCKFIF2c87YDfmCvAJke8QtE7IzjYDs7UFkTCM4ox+ph2bERUrxZbSCyEkHdjIZpKuMJfYWja/jgMqTMxdyOH9y8JLFbZsSXDIXDwqBlC6vVyl1fP90M35wuWcNTs6tctfVWVofEFbs="
|
||||
- GITTEST_INVASIVE_FS_SIZE=1
|
||||
matrix:
|
||||
- OPTIONS="-DTHREADSAFE=ON -DCMAKE_BUILD_TYPE=Release"
|
||||
- OPTIONS="-DTHREADSAFE=OFF -DBUILD_EXAMPLES=ON"
|
||||
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- sourceline: 'deb https://dl.bintray.com/libgit2/ci-dependencies trusty libgit2deps'
|
||||
key_url: 'https://bintray.com/user/downloadSubjectPublicKey?username=bintray'
|
||||
packages:
|
||||
- cmake
|
||||
- curl
|
||||
- libcurl3
|
||||
- libcurl3-gnutls
|
||||
- libcurl4-gnutls-dev
|
||||
- libssh2-1-dev
|
||||
- openssh-client
|
||||
- openssh-server
|
||||
- valgrind
|
||||
|
||||
sudo: false
|
||||
osx_image: xcode8.3
|
||||
|
||||
matrix:
|
||||
fast_finish: true
|
||||
exclude:
|
||||
- os: osx
|
||||
compiler: gcc
|
||||
include:
|
||||
- compiler: gcc
|
||||
env: COVERITY=1
|
||||
os: linux
|
||||
- compiler: gcc
|
||||
env:
|
||||
- VALGRIND=1
|
||||
OPTIONS="-DBUILD_CLAR=ON -DBUILD_EXAMPLES=OFF -DDEBUG_POOL=ON -DCMAKE_BUILD_TYPE=Debug"
|
||||
os: linux
|
||||
allow_failures:
|
||||
- env: COVERITY=1
|
||||
|
||||
install:
|
||||
- if [ "$TRAVIS_OS_NAME" = "osx" ]; then ./script/install-deps-${TRAVIS_OS_NAME}.sh; fi
|
||||
|
||||
# Run the Build script and tests
|
||||
script:
|
||||
- script/cibuild.sh
|
||||
|
||||
# Run Tests
|
||||
after_success:
|
||||
- if [ "$TRAVIS_OS_NAME" = "linux" -a -n "$VALGRIND" ]; then valgrind --leak-check=full --show-reachable=yes --suppressions=./libgit2_clar.supp _build/libgit2_clar -ionline; fi
|
||||
|
||||
# Only watch the development and master branches
|
||||
branches:
|
||||
only:
|
||||
- master
|
||||
- /^maint.*/
|
||||
|
||||
# Notify development list when needed
|
||||
notifications:
|
||||
irc:
|
||||
channels:
|
||||
- irc.freenode.net#libgit2
|
||||
on_success: change
|
||||
on_failure: always
|
||||
use_notice: true
|
||||
skip_join: true
|
||||
campfire:
|
||||
on_success: always
|
||||
on_failure: always
|
||||
rooms:
|
||||
- secure: "sH0dpPWMirbEe7AvLddZ2yOp8rzHalGmv0bYL/LIhVw3JDI589HCYckeLMSB\n3e/FeXw4bn0EqXWEXijVa4ijbilVY6d8oprdqMdWHEodng4KvY5vID3iZSGT\nxylhahO1XHmRynKQLOAvxlc93IlpVW38vQfby8giIY1nkpspb2w="
|
||||
48
CHANGELOG.md
48
CHANGELOG.md
@@ -1,3 +1,51 @@
|
||||
v0.26.8
|
||||
-------
|
||||
|
||||
This as a security release fixing the following list of issues:
|
||||
|
||||
- The function family `git__strtol` is used to parse integers
|
||||
from a buffer. As the functions do not take a buffer length as
|
||||
argument, they will scan either until the end of the current
|
||||
number or until a NUL byte is encountered. Many callers have
|
||||
been misusing the function and called it on potentially
|
||||
non-NUL-terminated buffers, resulting in possible out-of-bounds
|
||||
reads. Callers have been fixed to use `git__strntol` functions
|
||||
instead and `git__strtol` functions were removed.
|
||||
|
||||
- The function `git__strntol64` relied on the undefined behavior
|
||||
of signed integer overflows. While the code tried to detect
|
||||
such overflows after they have happened, this is unspecified
|
||||
behavior and may lead to weird behavior on uncommon platforms.
|
||||
|
||||
- In the case where `git__strntol32` was unable to parse an
|
||||
integer because it doesn't fit into an `int32_t`, it printed an
|
||||
error message containing the string that is currently being
|
||||
parsed. The code didn't truncate the string though, which
|
||||
caused it to print the complete string until a NUL byte is
|
||||
encountered and not only the currently parsed number. In case
|
||||
where the string was not NUL terminated, this could have lead
|
||||
to an out-of-bounds read.
|
||||
|
||||
- When parsing tags, all unknown fields that appear before the
|
||||
tag message are skipped. This skipping is done by using a plain
|
||||
`strstr(buffer, "\n\n")` to search for the two newlines that
|
||||
separate tag fields from tag message. As it is not possible to
|
||||
supply a buffer length to `strstr`, this call may skip over the
|
||||
buffer's end and thus result in an out of bounds read. As
|
||||
`strstr` may return a pointer that is out of bounds, the
|
||||
following computation of `buffer_end - buffer` will overflow
|
||||
and result in an allocation of an invalid length. Note that
|
||||
when reading objects from the object database, we make sure to
|
||||
always NUL terminate them, making the use of `strstr` safe.
|
||||
|
||||
- When parsing the "encoding" field of a commit, we may perform
|
||||
an out of bounds read due to using `git__prefixcmp` instead of
|
||||
`git__prefixncmp`. This can result in the parsed commit object
|
||||
containing uninitialized data in both its message encoding and
|
||||
message fields. Note that when reading objects from the object
|
||||
database, we make sure to always NUL terminate them, making the
|
||||
use of `strstr` safe.
|
||||
|
||||
v0.26.7
|
||||
-------
|
||||
|
||||
|
||||
@@ -677,7 +677,7 @@ IF (BUILD_CLAR)
|
||||
|
||||
ADD_CUSTOM_COMMAND(
|
||||
OUTPUT ${CLAR_PATH}/clar.suite
|
||||
COMMAND ${PYTHON_EXECUTABLE} generate.py -f -xonline -xstress .
|
||||
COMMAND ${PYTHON_EXECUTABLE} generate.py -f -xonline -xstress -xperf .
|
||||
DEPENDS ${SRC_TEST}
|
||||
WORKING_DIRECTORY ${CLAR_PATH}
|
||||
)
|
||||
@@ -703,17 +703,12 @@ IF (BUILD_CLAR)
|
||||
ENDIF ()
|
||||
|
||||
ENABLE_TESTING()
|
||||
IF (WINHTTP OR OPENSSL_FOUND OR SECURITY_FOUND)
|
||||
ADD_TEST(libgit2_clar libgit2_clar -ionline -xclone::local::git_style_unc_paths -xclone::local::standard_unc_paths_are_written_git_style)
|
||||
ELSE ()
|
||||
ADD_TEST(libgit2_clar libgit2_clar -v -xclone::local::git_style_unc_paths -xclone::local::standard_unc_paths_are_written_git_style)
|
||||
ENDIF ()
|
||||
|
||||
# Add a test target which runs the cred callback tests, to be
|
||||
# called after setting the url and user
|
||||
ADD_TEST(libgit2_clar-cred_callback libgit2_clar -v -sonline::clone::cred_callback)
|
||||
ADD_TEST(libgit2_clar-proxy_credentials_in_url libgit2_clar -v -sonline::clone::proxy_credentials_in_url)
|
||||
ADD_TEST(libgit2_clar-proxy_credentials_request libgit2_clar -v -sonline::clone::proxy_credentials_request)
|
||||
ADD_TEST(offline libgit2_clar -v -xonline)
|
||||
ADD_TEST(online libgit2_clar -v -sonline)
|
||||
ADD_TEST(gitdaemon libgit2_clar -v -sonline::push)
|
||||
ADD_TEST(ssh libgit2_clar -v -sonline::push -sonline::clone::ssh_cert -sonline::clone::ssh_with_paths)
|
||||
ADD_TEST(proxy libgit2_clar -v -sonline::clone::proxy_credentials_in_url -sonline::clone::proxy_credentials_request)
|
||||
ENDIF ()
|
||||
|
||||
IF (TAGS)
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
libgit2 - the Git linkable library
|
||||
==================================
|
||||
|
||||
[](http://travis-ci.org/libgit2/libgit2)
|
||||
[](https://ci.appveyor.com/project/libgit2/libgit2/branch/master)
|
||||
[](https://dev.azure.com/libgit2/libgit2/_build/latest?definitionId=7)
|
||||
[](https://scan.coverity.com/projects/639)
|
||||
|
||||
`libgit2` is a portable, pure C implementation of the Git core methods
|
||||
@@ -45,7 +44,7 @@ What It Can Do
|
||||
|
||||
libgit2 provides you with the ability to manage Git repositories in the
|
||||
programming language of your choice. It's used in production to power many
|
||||
applications including GitHub.com, Plastic SCM and Visual Studio Team Services.
|
||||
applications including GitHub.com, Plastic SCM and Azure DevOps.
|
||||
|
||||
It does not aim to replace the git tool or its user-facing commands. Some APIs
|
||||
resemble the plumbing commands as those align closely with the concepts of the
|
||||
|
||||
50
appveyor.yml
50
appveyor.yml
@@ -1,50 +0,0 @@
|
||||
version: '{build}'
|
||||
branches:
|
||||
only:
|
||||
- master
|
||||
- appveyor
|
||||
- /^maint.*/
|
||||
environment:
|
||||
GITTEST_INVASIVE_FS_STRUCTURE: 1
|
||||
GITTEST_INVASIVE_FS_SIZE: 1
|
||||
|
||||
matrix:
|
||||
- GENERATOR: "Visual Studio 11"
|
||||
ARCH: 32
|
||||
- GENERATOR: "Visual Studio 11 Win64"
|
||||
ARCH: 64
|
||||
- GENERATOR: "MSYS Makefiles"
|
||||
ARCH: i686 # this is for 32-bit MinGW-w64
|
||||
- GENERATOR: "MSYS Makefiles"
|
||||
ARCH: 64
|
||||
cache:
|
||||
- i686-4.9.2-release-win32-sjlj-rt_v3-rev1.7z
|
||||
- x86_64-4.9.2-release-win32-seh-rt_v3-rev1.7z
|
||||
|
||||
build_script:
|
||||
- ps: |
|
||||
mkdir build
|
||||
cd build
|
||||
if ($env:GENERATOR -ne "MSYS Makefiles") {
|
||||
cmake -D ENABLE_TRACE=ON -D BUILD_CLAR=ON -D MSVC_CRTDBG=ON .. -G"$env:GENERATOR"
|
||||
cmake --build . --config Debug
|
||||
}
|
||||
- cmd: |
|
||||
if "%GENERATOR%"=="MSYS Makefiles" (C:\MinGW\msys\1.0\bin\sh --login /c/projects/libgit2/script/appveyor-mingw.sh)
|
||||
test_script:
|
||||
- ps: |
|
||||
$ErrorActionPreference="Stop"
|
||||
Start-FileDownload https://github.com/ethomson/poxyproxy/releases/download/v0.1.0/poxyproxy-0.1.0.jar -FileName poxyproxy.jar
|
||||
# Run this early so we know it's ready by the time we need it
|
||||
$proxyJob = Start-Job { java -jar $Env:APPVEYOR_BUILD_FOLDER\build\poxyproxy.jar -d --port 8080 --credentials foo:bar }
|
||||
ctest -V -R libgit2_clar
|
||||
$env:GITTEST_REMOTE_URL="https://github.com/libgit2/non-existent"
|
||||
$env:GITTEST_REMOTE_USER="libgit2test"
|
||||
ctest -V -R libgit2_clar-cred_callback
|
||||
Receive-Job -Job $proxyJob
|
||||
$env:GITTEST_REMOTE_PROXY_URL = "http://foo:bar@localhost:8080"
|
||||
ctest -V -R libgit2_clar-proxy_credentials_in_url
|
||||
$env:GITTEST_REMOTE_PROXY_URL = "http://localhost:8080"
|
||||
$env:GITTEST_REMOTE_PROXY_USER = "foo"
|
||||
$env:GITTEST_REMOTE_PROXY_PASS = "bar"
|
||||
ctest -V -R libgit2_clar-proxy_credentials_request
|
||||
94
azure-pipelines.yml
Normal file
94
azure-pipelines.yml
Normal file
@@ -0,0 +1,94 @@
|
||||
resources:
|
||||
- repo: self
|
||||
|
||||
trigger:
|
||||
- master
|
||||
- maint/*
|
||||
|
||||
jobs:
|
||||
- job: linux_trusty_gcc_openssl
|
||||
displayName: 'Linux (Trusty; GCC; OpenSSL)'
|
||||
pool:
|
||||
vmImage: 'Ubuntu 16.04'
|
||||
steps:
|
||||
- template: ci/docker.yml
|
||||
parameters:
|
||||
imageName: 'libgit2/trusty-openssl:latest'
|
||||
environmentVariables: |
|
||||
CC=gcc
|
||||
LEAK_CHECK=valgrind
|
||||
|
||||
- job: linux_trusty_clang_openssl
|
||||
displayName: 'Linux (Trusty; Clang; OpenSSL)'
|
||||
pool:
|
||||
vmImage: 'Ubuntu 16.04'
|
||||
steps:
|
||||
- template: ci/docker.yml
|
||||
parameters:
|
||||
imageName: 'libgit2/trusty-openssl:latest'
|
||||
environmentVariables: |
|
||||
CC=clang
|
||||
LEAK_CHECK=valgrind
|
||||
|
||||
- job: macos
|
||||
displayName: 'macOS'
|
||||
pool:
|
||||
vmImage: 'macOS 10.13'
|
||||
steps:
|
||||
- bash: . '$(Build.SourcesDirectory)/ci/setup-osx.sh'
|
||||
displayName: Setup
|
||||
- template: ci/bash.yml
|
||||
parameters:
|
||||
environmentVariables:
|
||||
TMPDIR: $(Agent.TempDirectory)
|
||||
PKG_CONFIG_PATH: /usr/local/opt/openssl/lib/pkgconfig
|
||||
LEAK_CHECK: leaks
|
||||
|
||||
- job: windows_vs_amd64
|
||||
displayName: 'Windows (Visual Studio; amd64)'
|
||||
pool: Hosted
|
||||
steps:
|
||||
- template: ci/powershell.yml
|
||||
parameters:
|
||||
environmentVariables:
|
||||
CMAKE_OPTIONS: -DMSVC_CRTDBG=ON -G"Visual Studio 12 2013 Win64"
|
||||
|
||||
- job: windows_vs_x86
|
||||
displayName: 'Windows (Visual Studio; x86)'
|
||||
pool: Hosted
|
||||
steps:
|
||||
- template: ci/powershell.yml
|
||||
parameters:
|
||||
environmentVariables:
|
||||
CMAKE_OPTIONS: -DMSVC_CRTDBG=ON -G"Visual Studio 12 2013"
|
||||
|
||||
- job: windows_mingw_amd64
|
||||
displayName: 'Windows (MinGW; amd64)'
|
||||
pool: Hosted
|
||||
steps:
|
||||
- powershell: . '$(Build.SourcesDirectory)\ci\setup-mingw.ps1'
|
||||
displayName: Setup
|
||||
env:
|
||||
TEMP: $(Agent.TempDirectory)
|
||||
ARCH: amd64
|
||||
- template: ci/powershell.yml
|
||||
parameters:
|
||||
environmentVariables:
|
||||
CMAKE_OPTIONS: -G"MinGW Makefiles"
|
||||
PATH: $(Agent.TempDirectory)\mingw64\bin;C:\ProgramData\Oracle\Java\javapath;C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\WindowsPowerShell\v1.0\;C:\Program Files (x86)\CMake\bin
|
||||
|
||||
- job: windows_mingw_x86
|
||||
displayName: 'Windows (MinGW; x86)'
|
||||
pool: Hosted
|
||||
steps:
|
||||
- powershell: . '$(Build.SourcesDirectory)\ci\setup-mingw.ps1'
|
||||
displayName: Setup
|
||||
workingDirectory: '$(Build.BinariesDirectory)'
|
||||
env:
|
||||
TEMP: $(Agent.TempDirectory)
|
||||
ARCH: x86
|
||||
- template: ci/powershell.yml
|
||||
parameters:
|
||||
environmentVariables:
|
||||
CMAKE_OPTIONS: -G"MinGW Makefiles"
|
||||
PATH: $(Agent.TempDirectory)\mingw32\bin;C:\ProgramData\Oracle\Java\javapath;C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\WindowsPowerShell\v1.0\;C:\Program Files (x86)\CMake\bin
|
||||
17
ci/bash.yml
Normal file
17
ci/bash.yml
Normal file
@@ -0,0 +1,17 @@
|
||||
# These are the steps used for building on machines with bash.
|
||||
steps:
|
||||
- bash: . '$(Build.SourcesDirectory)/ci/build.sh'
|
||||
displayName: Build
|
||||
workingDirectory: '$(Build.BinariesDirectory)'
|
||||
env: ${{ parameters.environmentVariables }}
|
||||
- bash: . '$(Build.SourcesDirectory)/ci/test.sh'
|
||||
displayName: Test
|
||||
workingDirectory: '$(Build.BinariesDirectory)'
|
||||
env: ${{ parameters.environmentVariables }}
|
||||
- task: PublishTestResults@2
|
||||
displayName: Publish Test Results
|
||||
condition: succeededOrFailed()
|
||||
inputs:
|
||||
testResultsFiles: 'results_*.xml'
|
||||
searchFolder: '$(Build.BinariesDirectory)'
|
||||
mergeTestResults: true
|
||||
30
ci/build.ps1
Normal file
30
ci/build.ps1
Normal file
@@ -0,0 +1,30 @@
|
||||
Set-StrictMode -Version Latest
|
||||
|
||||
$ErrorActionPreference = "Stop"
|
||||
$PSDefaultParameterValues['*:ErrorAction'] = 'Stop'
|
||||
|
||||
if ($Env:SOURCE_DIR) { $SourceDirectory = $Env:SOURCE_DIR } else { $SourceDirectory = Split-Path (Split-Path $MyInvocation.MyCommand.Path -Parent) -Parent }
|
||||
$BuildDirectory = $(Get-Location).Path
|
||||
|
||||
Write-Host "Source directory: ${SourceDirectory}"
|
||||
Write-Host "Build directory: ${BuildDirectory}"
|
||||
Write-Host ""
|
||||
Write-Host "Operating system version:"
|
||||
Get-CimInstance Win32_OperatingSystem | Select-Object Caption, Version, ServicePackMajorVersion, BuildNumber, OSArchitecture | Format-List
|
||||
Write-Host "PATH: ${Env:PATH}"
|
||||
Write-Host ""
|
||||
|
||||
Write-Host "##############################################################################"
|
||||
Write-Host "## Configuring build environment"
|
||||
Write-Host "##############################################################################"
|
||||
|
||||
Invoke-Expression "cmake ${SourceDirectory} -DBUILD_EXAMPLES=ON ${Env:CMAKE_OPTIONS}"
|
||||
if ($LastExitCode -ne 0) { [Environment]::Exit($LastExitCode) }
|
||||
|
||||
Write-Host ""
|
||||
Write-Host "##############################################################################"
|
||||
Write-Host "## Building libgit2"
|
||||
Write-Host "##############################################################################"
|
||||
|
||||
cmake --build .
|
||||
if ($LastExitCode -ne 0) { [Environment]::Exit($LastExitCode) }
|
||||
39
ci/build.sh
Executable file
39
ci/build.sh
Executable file
@@ -0,0 +1,39 @@
|
||||
#!/usr/bin/env bash
|
||||
#
|
||||
# Environment variables:
|
||||
#
|
||||
# SOURCE_DIR: Set to the directory of the libgit2 source (optional)
|
||||
# If not set, it will be derived relative to this script.
|
||||
|
||||
set -e
|
||||
|
||||
SOURCE_DIR=${SOURCE_DIR:-$( cd "$( dirname "${BASH_SOURCE[0]}" )" && dirname $( pwd ) )}
|
||||
BUILD_DIR=$(pwd)
|
||||
CC=${CC:-cc}
|
||||
|
||||
indent() { sed "s/^/ /"; }
|
||||
|
||||
echo "Source directory: ${SOURCE_DIR}"
|
||||
echo "Build directory: ${BUILD_DIR}"
|
||||
echo ""
|
||||
echo "Operating system version:"
|
||||
uname -a 2>&1 | indent
|
||||
echo "CMake version:"
|
||||
cmake --version 2>&1 | indent
|
||||
echo "Compiler version:"
|
||||
$CC --version 2>&1 | indent
|
||||
echo ""
|
||||
|
||||
echo "##############################################################################"
|
||||
echo "## Configuring build environment"
|
||||
echo "##############################################################################"
|
||||
|
||||
echo cmake ${SOURCE_DIR} -DBUILD_EXAMPLES=ON ${CMAKE_OPTIONS}
|
||||
cmake ${SOURCE_DIR} -DBUILD_EXAMPLES=ON ${CMAKE_OPTIONS}
|
||||
|
||||
echo ""
|
||||
echo "##############################################################################"
|
||||
echo "## Building libgit2"
|
||||
echo "##############################################################################"
|
||||
|
||||
cmake --build .
|
||||
@@ -1,17 +1,13 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
# Only run this on our branches
|
||||
echo "Branch: $TRAVIS_BRANCH | Pull request: $TRAVIS_PULL_REQUEST | Slug: $TRAVIS_REPO_SLUG"
|
||||
if [ "$TRAVIS_BRANCH" != "master" -o "$TRAVIS_PULL_REQUEST" != "false" -o "$TRAVIS_REPO_SLUG" != "libgit2/libgit2" ];
|
||||
then
|
||||
echo "Only analyzing the 'master' brach of the main repository."
|
||||
exit 0
|
||||
fi
|
||||
set -e
|
||||
|
||||
# Environment check
|
||||
[ -z "$COVERITY_TOKEN" ] && echo "Need to set a coverity token" && exit 1
|
||||
|
||||
SOURCE_DIR=${SOURCE_DIR:-$( cd "$( dirname "${BASH_SOURCE[0]}" )" && dirname $( pwd ) )}
|
||||
BUILD_DIR=$(pwd)
|
||||
|
||||
case $(uname -m) in
|
||||
i?86) BITS=32 ;;
|
||||
amd64|x86_64) BITS=64 ;;
|
||||
@@ -32,31 +28,29 @@ if [ ! -d "$TOOL_BASE" ]; then
|
||||
ln -s "$TOOL_DIR" "$TOOL_BASE"/cov-analysis
|
||||
fi
|
||||
|
||||
cp script/user_nodefs.h "$TOOL_BASE"/cov-analysis/config/user_nodefs.h
|
||||
cp "${SOURCE_DIR}/script/user_nodefs.h" "$TOOL_BASE"/cov-analysis/config/user_nodefs.h
|
||||
|
||||
COV_BUILD="$TOOL_BASE/cov-analysis/bin/cov-build"
|
||||
|
||||
# Configure and build
|
||||
rm -rf _build
|
||||
mkdir _build
|
||||
cd _build
|
||||
cmake .. -DTHREADSAFE=ON
|
||||
cmake ${SOURCE_DIR}
|
||||
|
||||
COVERITY_UNSUPPORTED=1 \
|
||||
$COV_BUILD --dir cov-int \
|
||||
cmake --build .
|
||||
|
||||
# Upload results
|
||||
tar czf libgit2.tgz cov-int
|
||||
SHA=$(git rev-parse --short HEAD)
|
||||
SHA=$(cd ${SOURCE_DIR} && git rev-parse --short HEAD)
|
||||
|
||||
HTML="$(curl \
|
||||
--silent \
|
||||
--write-out "\n%{http_code}" \
|
||||
--form token="$COVERITY_TOKEN" \
|
||||
--form email=bs@github.com \
|
||||
--form email=libgit2@gmail.com \
|
||||
--form file=@libgit2.tgz \
|
||||
--form version="$SHA" \
|
||||
--form description="Travis build" \
|
||||
--form description="libgit2 build" \
|
||||
https://scan.coverity.com/builds?project=libgit2)"
|
||||
# Body is everything up to the last line
|
||||
BODY="$(echo "$HTML" | head -n-1)"
|
||||
@@ -65,7 +59,7 @@ STATUS_CODE="$(echo "$HTML" | tail -n1)"
|
||||
|
||||
echo "${BODY}"
|
||||
|
||||
if [ "${STATUS_CODE}" != "201" ]; then
|
||||
if [ "${STATUS_CODE}" != "200" -a "${STATUS_CODE}" != "201" ]; then
|
||||
echo "Received error code ${STATUS_CODE} from Coverity"
|
||||
exit 1
|
||||
fi
|
||||
33
ci/docker.yml
Normal file
33
ci/docker.yml
Normal file
@@ -0,0 +1,33 @@
|
||||
# These are the steps used in a container-based build in VSTS.
|
||||
steps:
|
||||
- task: docker@0
|
||||
displayName: Build
|
||||
inputs:
|
||||
action: 'Run an image'
|
||||
imageName: ${{ parameters.imageName }}
|
||||
volumes: |
|
||||
$(Build.SourcesDirectory):/src
|
||||
$(Build.BinariesDirectory):/build
|
||||
envVars: ${{ parameters.environmentVariables }}
|
||||
workDir: '/build'
|
||||
containerCommand: '/src/ci/build.sh'
|
||||
detached: false
|
||||
- task: docker@0
|
||||
displayName: Test
|
||||
inputs:
|
||||
action: 'Run an image'
|
||||
imageName: ${{ parameters.imageName }}
|
||||
volumes: |
|
||||
$(Build.SourcesDirectory):/src
|
||||
$(Build.BinariesDirectory):/build
|
||||
envVars: ${{ parameters.environmentVariables }}
|
||||
workDir: '/build'
|
||||
containerCommand: '/src/ci/test.sh'
|
||||
detached: false
|
||||
- task: publishtestresults@2
|
||||
displayName: Publish Test Results
|
||||
condition: succeededOrFailed()
|
||||
inputs:
|
||||
testResultsFiles: 'results_*.xml'
|
||||
searchFolder: '$(Build.BinariesDirectory)'
|
||||
mergeTestResults: true
|
||||
22
ci/nightly.yml
Normal file
22
ci/nightly.yml
Normal file
@@ -0,0 +1,22 @@
|
||||
resources:
|
||||
- repo: self
|
||||
|
||||
jobs:
|
||||
- job: coverity
|
||||
displayName: 'Coverity'
|
||||
pool:
|
||||
vmImage: 'Ubuntu 16.04'
|
||||
steps:
|
||||
- task: Docker@0
|
||||
displayName: Build
|
||||
inputs:
|
||||
action: 'Run an image'
|
||||
imageName: 'libgit2/trusty-openssl:latest'
|
||||
volumes: |
|
||||
$(Build.SourcesDirectory):/src
|
||||
$(Build.BinariesDirectory):/build
|
||||
envVars: |
|
||||
COVERITY_TOKEN=$(COVERITY_TOKEN)
|
||||
workDir: '/build'
|
||||
containerCommand: '/src/ci/coverity.sh'
|
||||
detached: false
|
||||
17
ci/powershell.yml
Normal file
17
ci/powershell.yml
Normal file
@@ -0,0 +1,17 @@
|
||||
# These are the steps used for building on machines with PowerShell.
|
||||
steps:
|
||||
- powershell: . '$(Build.SourcesDirectory)\ci\build.ps1'
|
||||
displayName: Build
|
||||
workingDirectory: '$(Build.BinariesDirectory)'
|
||||
env: ${{ parameters.environmentVariables }}
|
||||
- powershell: . '$(Build.SourcesDirectory)\ci\test.ps1'
|
||||
displayName: Test
|
||||
workingDirectory: '$(Build.BinariesDirectory)'
|
||||
env: ${{ parameters.environmentVariables }}
|
||||
- task: PublishTestResults@2
|
||||
displayName: Publish Test Results
|
||||
condition: succeededOrFailed()
|
||||
inputs:
|
||||
testResultsFiles: 'results_*.xml'
|
||||
searchFolder: '$(Build.BinariesDirectory)'
|
||||
mergeTestResults: true
|
||||
13
ci/setup-linux.sh
Executable file
13
ci/setup-linux.sh
Executable file
@@ -0,0 +1,13 @@
|
||||
#!/bin/sh
|
||||
|
||||
set -e
|
||||
set -x
|
||||
|
||||
TMPDIR=${TMPDIR:-/tmp}
|
||||
|
||||
if [ -z "$SKIP_APT" ]; then
|
||||
apt-get update
|
||||
apt-get -y install build-essential pkg-config clang cmake openssl libssl-dev libssh2-1-dev libcurl4-gnutls-dev openssh-server
|
||||
fi
|
||||
|
||||
mkdir -p /var/run/sshd
|
||||
25
ci/setup-mingw.ps1
Normal file
25
ci/setup-mingw.ps1
Normal file
@@ -0,0 +1,25 @@
|
||||
Set-StrictMode -Version Latest
|
||||
|
||||
$ErrorActionPreference = "Stop"
|
||||
$PSDefaultParameterValues['*:ErrorAction'] = 'Stop'
|
||||
|
||||
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
|
||||
|
||||
[Reflection.Assembly]::LoadWithPartialName("System.IO.Compression.FileSystem");
|
||||
|
||||
Write-Host "##############################################################################"
|
||||
Write-Host "## Downloading mingw"
|
||||
Write-Host "##############################################################################"
|
||||
|
||||
if ($env:ARCH -eq "amd64") {
|
||||
$mingw_uri = "https://bintray.com/libgit2/build-dependencies/download_file?file_path=mingw-w64-x86_64-8.1.0-release-win32-seh-rt_v6-rev0.zip"
|
||||
$platform = "x86_64"
|
||||
} else {
|
||||
$mingw_uri = "https://bintray.com/libgit2/build-dependencies/download_file?file_path=mingw-w64-i686-8.1.0-release-win32-sjlj-rt_v6-rev0.zip"
|
||||
$platform = "x86"
|
||||
}
|
||||
|
||||
$wc = New-Object net.webclient
|
||||
$wc.Downloadfile($mingw_uri, "${Env:TEMP}/mingw-${Env:ARCH}.zip")
|
||||
|
||||
[System.IO.Compression.ZipFile]::ExtractToDirectory("${Env:TEMP}/mingw-${Env:ARCH}.zip", $Env:TEMP)
|
||||
8
ci/setup-osx.sh
Executable file
8
ci/setup-osx.sh
Executable file
@@ -0,0 +1,8 @@
|
||||
#!/bin/sh
|
||||
|
||||
set -x
|
||||
|
||||
brew update
|
||||
brew install pkgconfig zlib curl openssl libssh2
|
||||
|
||||
ln -s /Applications/Xcode.app/Contents/Developer/usr/lib/libLeaksAtExit.dylib /usr/local/lib
|
||||
72
ci/test.ps1
Normal file
72
ci/test.ps1
Normal file
@@ -0,0 +1,72 @@
|
||||
Set-StrictMode -Version Latest
|
||||
|
||||
$ErrorActionPreference = "Stop"
|
||||
$PSDefaultParameterValues['*:ErrorAction'] = 'Stop'
|
||||
|
||||
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
|
||||
|
||||
$SourceDir = Split-Path (Split-Path (Get-Variable MyInvocation).Value.MyCommand.Path)
|
||||
$BuildDir = Get-Location
|
||||
$global:Success = $true
|
||||
|
||||
if ($Env:SKIP_TESTS) { exit }
|
||||
|
||||
# Ask ctest what it would run if we were to invoke it directly. This lets
|
||||
# us manage the test configuration in a single place (tests/CMakeLists.txt)
|
||||
# instead of running clar here as well. But it allows us to wrap our test
|
||||
# harness with a leak checker like valgrind. Append the option to write
|
||||
# JUnit-style XML files.
|
||||
function run_test {
|
||||
$TestName = $args[0]
|
||||
|
||||
$TestCommand = (ctest -N -V -R "^$TestName$") -join "`n" -replace "(?ms).*\n^[0-9]*: Test command: ","" -replace "\n.*",""
|
||||
$TestCommand += " -r${BuildDir}\results_${TestName}.xml"
|
||||
|
||||
Write-Host $TestCommand
|
||||
Invoke-Expression $TestCommand
|
||||
|
||||
if ($LastExitCode -ne 0) { $global:Success = $false }
|
||||
}
|
||||
|
||||
Write-Host "##############################################################################"
|
||||
Write-Host "## Configuring test environment"
|
||||
Write-Host "##############################################################################"
|
||||
|
||||
if (-not $Env:SKIP_PROXY_TESTS) {
|
||||
Write-Host ""
|
||||
Write-Host "Starting HTTP proxy..."
|
||||
Invoke-WebRequest -Method GET -Uri https://github.com/ethomson/poxyproxy/releases/download/v0.1.0/poxyproxy-0.1.0.jar -OutFile poxyproxy.jar
|
||||
javaw -jar poxyproxy.jar -d --port 8080 --credentials foo:bar
|
||||
}
|
||||
|
||||
Write-Host ""
|
||||
Write-Host "##############################################################################"
|
||||
Write-Host "## Running (offline) tests"
|
||||
Write-Host "##############################################################################"
|
||||
|
||||
run_test offline
|
||||
|
||||
if (-not $Env:SKIP_ONLINE_TESTS) {
|
||||
Write-Host ""
|
||||
Write-Host "##############################################################################"
|
||||
Write-Host "## Running (online) tests"
|
||||
Write-Host "##############################################################################"
|
||||
|
||||
run_test online
|
||||
}
|
||||
|
||||
if (-not $Env:SKIP_PROXY_TESTS) {
|
||||
Write-Host ""
|
||||
Write-Host "Running proxy tests"
|
||||
Write-Host ""
|
||||
|
||||
$Env:GITTEST_REMOTE_PROXY_URL="localhost:8080"
|
||||
$Env:GITTEST_REMOTE_PROXY_USER="foo"
|
||||
$Env:GITTEST_REMOTE_PROXY_PASS="bar"
|
||||
|
||||
run_test proxy
|
||||
|
||||
taskkill /F /IM javaw.exe
|
||||
}
|
||||
|
||||
if (-Not $global:Success) { exit 1 }
|
||||
198
ci/test.sh
Executable file
198
ci/test.sh
Executable file
@@ -0,0 +1,198 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -e
|
||||
|
||||
if [ -n "$SKIP_TESTS" ]; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
SOURCE_DIR=${SOURCE_DIR:-$( cd "$( dirname "${BASH_SOURCE[0]}" )" && dirname $( pwd ) )}
|
||||
BUILD_DIR=$(pwd)
|
||||
TMPDIR=${TMPDIR:-/tmp}
|
||||
USER=${USER:-$(whoami)}
|
||||
|
||||
SUCCESS=1
|
||||
|
||||
VALGRIND="valgrind --leak-check=full --show-reachable=yes --error-exitcode=125 --num-callers=50 --suppressions=\"$SOURCE_DIR/libgit2_clar.supp\""
|
||||
LEAKS="MallocStackLogging=1 MallocScribble=1 leaks -quiet -atExit -- nohup"
|
||||
|
||||
cleanup() {
|
||||
echo "Cleaning up..."
|
||||
|
||||
if [ ! -z "$GITDAEMON_DIR" -a -f "${GITDAEMON_DIR}/pid" ]; then
|
||||
echo "Stopping git daemon..."
|
||||
kill $(cat "${GITDAEMON_DIR}/pid")
|
||||
fi
|
||||
|
||||
if [ ! -z "$SSHD_DIR" -a -f "${SSHD_DIR}/pid" ]; then
|
||||
echo "Stopping SSH..."
|
||||
kill $(cat "${SSHD_DIR}/pid")
|
||||
fi
|
||||
|
||||
echo "Done."
|
||||
}
|
||||
|
||||
failure() {
|
||||
echo "Test exited with code: $1"
|
||||
SUCCESS=0
|
||||
}
|
||||
|
||||
# Ask ctest what it would run if we were to invoke it directly. This lets
|
||||
# us manage the test configuration in a single place (tests/CMakeLists.txt)
|
||||
# instead of running clar here as well. But it allows us to wrap our test
|
||||
# harness with a leak checker like valgrind. Append the option to write
|
||||
# JUnit-style XML files.
|
||||
run_test() {
|
||||
TEST_CMD=$(ctest -N -V -R "^${1}$" | sed -n 's/^[0-9]*: Test command: //p')
|
||||
TEST_CMD="${TEST_CMD} -r${BUILD_DIR}/results_${1}.xml"
|
||||
|
||||
if [ "$LEAK_CHECK" = "valgrind" ]; then
|
||||
RUNNER="$VALGRIND $TEST_CMD"
|
||||
elif [ "$LEAK_CHECK" = "leaks" ]; then
|
||||
RUNNER="$LEAKS $TEST_CMD"
|
||||
else
|
||||
RUNNER="$TEST_CMD"
|
||||
fi
|
||||
|
||||
eval $RUNNER || failure
|
||||
}
|
||||
|
||||
# Configure the test environment; run them early so that we're certain
|
||||
# that they're started by the time we need them.
|
||||
|
||||
echo "##############################################################################"
|
||||
echo "## Configuring test environment"
|
||||
echo "##############################################################################"
|
||||
|
||||
if [ -z "$SKIP_GITDAEMON_TESTS" ]; then
|
||||
echo "Starting git daemon..."
|
||||
GITDAEMON_DIR=`mktemp -d ${TMPDIR}/gitdaemon.XXXXXXXX`
|
||||
git init --bare "${GITDAEMON_DIR}/test.git"
|
||||
git daemon --listen=localhost --export-all --enable=receive-pack --pid-file="${GITDAEMON_DIR}/pid" --base-path="${GITDAEMON_DIR}" "${GITDAEMON_DIR}" 2>/dev/null &
|
||||
fi
|
||||
|
||||
if [ -z "$SKIP_PROXY_TESTS" ]; then
|
||||
echo "Starting HTTP proxy..."
|
||||
curl -L https://github.com/ethomson/poxyproxy/releases/download/v0.1.0/poxyproxy-0.1.0.jar >poxyproxy.jar
|
||||
java -jar poxyproxy.jar -d --port 8080 --credentials foo:bar >/dev/null 2>&1 &
|
||||
fi
|
||||
|
||||
if [ -z "$SKIP_SSH_TESTS" ]; then
|
||||
echo "Starting ssh daemon..."
|
||||
HOME=`mktemp -d ${TMPDIR}/home.XXXXXXXX`
|
||||
SSHD_DIR=`mktemp -d ${TMPDIR}/sshd.XXXXXXXX`
|
||||
git init --bare "${SSHD_DIR}/test.git"
|
||||
cat >"${SSHD_DIR}/sshd_config" <<-EOF
|
||||
Port 2222
|
||||
ListenAddress 0.0.0.0
|
||||
Protocol 2
|
||||
HostKey ${SSHD_DIR}/id_rsa
|
||||
PidFile ${SSHD_DIR}/pid
|
||||
AuthorizedKeysFile ${HOME}/.ssh/authorized_keys
|
||||
LogLevel DEBUG
|
||||
RSAAuthentication yes
|
||||
PasswordAuthentication yes
|
||||
PubkeyAuthentication yes
|
||||
ChallengeResponseAuthentication no
|
||||
StrictModes no
|
||||
# Required here as sshd will simply close connection otherwise
|
||||
UsePAM no
|
||||
EOF
|
||||
ssh-keygen -t rsa -f "${SSHD_DIR}/id_rsa" -N "" -q
|
||||
/usr/sbin/sshd -f "${SSHD_DIR}/sshd_config" -E "${SSHD_DIR}/log"
|
||||
|
||||
# Set up keys
|
||||
mkdir "${HOME}/.ssh"
|
||||
ssh-keygen -t rsa -f "${HOME}/.ssh/id_rsa" -N "" -q
|
||||
cat "${HOME}/.ssh/id_rsa.pub" >>"${HOME}/.ssh/authorized_keys"
|
||||
while read algorithm key comment; do
|
||||
echo "[localhost]:2222 $algorithm $key" >>"${HOME}/.ssh/known_hosts"
|
||||
done <"${SSHD_DIR}/id_rsa.pub"
|
||||
|
||||
# Get the fingerprint for localhost and remove the colons so we can
|
||||
# parse it as a hex number. Older versions have a different output
|
||||
# format.
|
||||
if [[ $(ssh -V 2>&1) == OpenSSH_6* ]]; then
|
||||
SSH_FINGERPRINT=$(ssh-keygen -F '[localhost]:2222' -f "${HOME}/.ssh/known_hosts" -l | tail -n 1 | cut -d ' ' -f 2 | tr -d ':')
|
||||
else
|
||||
SSH_FINGERPRINT=$(ssh-keygen -E md5 -F '[localhost]:2222' -f "${HOME}/.ssh/known_hosts" -l | tail -n 1 | cut -d ' ' -f 3 | cut -d : -f2- | tr -d :)
|
||||
fi
|
||||
fi
|
||||
|
||||
# Run the tests that do not require network connectivity.
|
||||
|
||||
if [ -z "$SKIP_OFFLINE_TESTS" ]; then
|
||||
echo ""
|
||||
echo "##############################################################################"
|
||||
echo "## Running (offline) tests"
|
||||
echo "##############################################################################"
|
||||
|
||||
run_test offline
|
||||
fi
|
||||
|
||||
if [ -z "$SKIP_ONLINE_TESTS" ]; then
|
||||
# Run the various online tests. The "online" test suite only includes the
|
||||
# default online tests that do not require additional configuration. The
|
||||
# "proxy" and "ssh" test suites require further setup.
|
||||
|
||||
echo ""
|
||||
echo "##############################################################################"
|
||||
echo "## Running (online) tests"
|
||||
echo "##############################################################################"
|
||||
|
||||
run_test online
|
||||
fi
|
||||
|
||||
if [ -z "$SKIP_GITDAEMON_TESTS" ]; then
|
||||
echo ""
|
||||
echo "Running gitdaemon tests"
|
||||
echo ""
|
||||
|
||||
export GITTEST_REMOTE_URL="git://localhost/test.git"
|
||||
run_test gitdaemon
|
||||
unset GITTEST_REMOTE_URL
|
||||
fi
|
||||
|
||||
if [ -z "$SKIP_PROXY_TESTS" ]; then
|
||||
echo ""
|
||||
echo "Running proxy tests"
|
||||
echo ""
|
||||
|
||||
export GITTEST_REMOTE_PROXY_URL="localhost:8080"
|
||||
export GITTEST_REMOTE_PROXY_USER="foo"
|
||||
export GITTEST_REMOTE_PROXY_PASS="bar"
|
||||
run_test proxy
|
||||
unset GITTEST_REMOTE_PROXY_URL
|
||||
unset GITTEST_REMOTE_PROXY_USER
|
||||
unset GITTEST_REMOTE_PROXY_PASS
|
||||
fi
|
||||
|
||||
if [ -z "$SKIP_SSH_TESTS" ]; then
|
||||
echo ""
|
||||
echo "Running ssh tests"
|
||||
echo ""
|
||||
|
||||
export GITTEST_REMOTE_URL="ssh://localhost:2222/$SSHD_DIR/test.git"
|
||||
export GITTEST_REMOTE_USER=$USER
|
||||
export GITTEST_REMOTE_SSH_KEY="${HOME}/.ssh/id_rsa"
|
||||
export GITTEST_REMOTE_SSH_PUBKEY="${HOME}/.ssh/id_rsa.pub"
|
||||
export GITTEST_REMOTE_SSH_PASSPHRASE=""
|
||||
export GITTEST_REMOTE_SSH_FINGERPRINT="${SSH_FINGERPRINT}"
|
||||
run_test ssh
|
||||
unset GITTEST_REMOTE_URL
|
||||
unset GITTEST_REMOTE_USER
|
||||
unset GITTEST_REMOTE_SSH_KEY
|
||||
unset GITTEST_REMOTE_SSH_PUBKEY
|
||||
unset GITTEST_REMOTE_SSH_PASSPHRASE
|
||||
unset GITTEST_REMOTE_SSH_FINGERPRINT
|
||||
fi
|
||||
|
||||
cleanup
|
||||
|
||||
if [ "$SUCCESS" -ne "1" ]; then
|
||||
echo "Some tests failed."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Success."
|
||||
exit 0
|
||||
@@ -16,6 +16,43 @@
|
||||
# define UNUSED(x) x
|
||||
#endif
|
||||
|
||||
static int readline(char **out)
|
||||
{
|
||||
int c, error = 0, length = 0, allocated = 0;
|
||||
char *line = NULL;
|
||||
|
||||
errno = 0;
|
||||
|
||||
while ((c = getchar()) != EOF) {
|
||||
if (length == allocated) {
|
||||
allocated += 16;
|
||||
|
||||
if ((line = realloc(line, allocated)) == NULL) {
|
||||
error = -1;
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
||||
if (c == '\n')
|
||||
break;
|
||||
|
||||
line[length++] = c;
|
||||
}
|
||||
|
||||
if (errno != 0) {
|
||||
error = -1;
|
||||
goto error;
|
||||
}
|
||||
|
||||
line[length] = '\0';
|
||||
*out = line;
|
||||
line = NULL;
|
||||
error = length;
|
||||
error:
|
||||
free(line);
|
||||
return error;
|
||||
}
|
||||
|
||||
int cred_acquire_cb(git_cred **out,
|
||||
const char * UNUSED(url),
|
||||
const char * UNUSED(username_from_url),
|
||||
@@ -26,14 +63,14 @@ int cred_acquire_cb(git_cred **out,
|
||||
int error;
|
||||
|
||||
printf("Username: ");
|
||||
if (getline(&username, NULL, stdin) < 0) {
|
||||
if (readline(&username) < 0) {
|
||||
fprintf(stderr, "Unable to read username: %s", strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Yup. Right there on your terminal. Careful where you copy/paste output. */
|
||||
printf("Password: ");
|
||||
if (getline(&password, NULL, stdin) < 0) {
|
||||
if (readline(&password) < 0) {
|
||||
fprintf(stderr, "Unable to read password: %s", strerror(errno));
|
||||
free(username);
|
||||
return -1;
|
||||
|
||||
@@ -7,10 +7,10 @@
|
||||
#ifndef INCLUDE_git_version_h__
|
||||
#define INCLUDE_git_version_h__
|
||||
|
||||
#define LIBGIT2_VERSION "0.26.7"
|
||||
#define LIBGIT2_VERSION "0.26.8"
|
||||
#define LIBGIT2_VER_MAJOR 0
|
||||
#define LIBGIT2_VER_MINOR 26
|
||||
#define LIBGIT2_VER_REVISION 7
|
||||
#define LIBGIT2_VER_REVISION 8
|
||||
#define LIBGIT2_VER_PATCH 0
|
||||
|
||||
#define LIBGIT2_SOVERSION 26
|
||||
|
||||
@@ -47,3 +47,28 @@
|
||||
...
|
||||
fun:__check_pf
|
||||
}
|
||||
|
||||
{
|
||||
ignore-curl-global-init
|
||||
Memcheck:Leak
|
||||
...
|
||||
fun:curl_global_init
|
||||
}
|
||||
|
||||
{
|
||||
ignore-libssh2-gcrypt-leak
|
||||
Memcheck:Leak
|
||||
...
|
||||
fun:gcry_control
|
||||
obj:*libssh2.so*
|
||||
}
|
||||
|
||||
{
|
||||
ignore-noai6ai_cached-double-free
|
||||
Memcheck:Free
|
||||
fun:free
|
||||
fun:__libc_freeres
|
||||
...
|
||||
fun:exit
|
||||
...
|
||||
}
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
#!/bin/sh
|
||||
set -e
|
||||
cd `dirname "$0"`/..
|
||||
if [ "$ARCH" = "i686" ]; then
|
||||
f=i686-4.9.2-release-win32-sjlj-rt_v3-rev1.7z
|
||||
if ! [ -e $f ]; then
|
||||
curl -LsSO http://sourceforge.net/projects/mingw-w64/files/Toolchains%20targetting%20Win32/Personal%20Builds/mingw-builds/4.9.2/threads-win32/sjlj/$f
|
||||
fi
|
||||
7z x $f > /dev/null
|
||||
export PATH=`pwd`/mingw32/bin:$PATH
|
||||
else
|
||||
f=x86_64-4.9.2-release-win32-seh-rt_v3-rev1.7z
|
||||
if ! [ -e $f ]; then
|
||||
curl -LsSO http://sourceforge.net/projects/mingw-w64/files/Toolchains%20targetting%20Win64/Personal%20Builds/mingw-builds/4.9.2/threads-win32/seh/$f
|
||||
fi
|
||||
7z x $f > /dev/null
|
||||
export PATH=`pwd`/mingw64/bin:$PATH
|
||||
fi
|
||||
cd build
|
||||
gcc --version
|
||||
cmake --version
|
||||
cmake -D ENABLE_TRACE=ON -D BUILD_CLAR=ON .. -G"$GENERATOR"
|
||||
cmake --build . --config RelWithDebInfo
|
||||
@@ -2,87 +2,26 @@
|
||||
|
||||
set -x
|
||||
|
||||
if [ -n "$COVERITY" ];
|
||||
then
|
||||
./script/coverity.sh;
|
||||
exit $?;
|
||||
if [ -n "$COVERITY" ]; then
|
||||
./script/coverity.sh
|
||||
exit $?
|
||||
fi
|
||||
|
||||
if [ "$TRAVIS_OS_NAME" = "osx" ]; then
|
||||
export PKG_CONFIG_PATH=$(ls -d /usr/local/Cellar/{curl,zlib}/*/lib/pkgconfig | paste -s -d':' -)
|
||||
fi
|
||||
|
||||
# Should we ask Travis to cache this file?
|
||||
curl -L https://github.com/ethomson/poxyproxy/releases/download/v0.1.0/poxyproxy-0.1.0.jar >poxyproxy.jar || exit $?
|
||||
# Run this early so we know it's ready by the time we need it
|
||||
java -jar poxyproxy.jar -d --port 8080 --credentials foo:bar &
|
||||
# Set up a ramdisk for us to put our test data on to speed up tests on macOS
|
||||
export CLAR_TMP="$HOME"/_clar_tmp
|
||||
mkdir -p $CLAR_TMP
|
||||
|
||||
# 5*2M sectors aka ~5GB of space
|
||||
device=$(hdiutil attach -nomount ram://$((5 * 2 * 1024 * 1024)))
|
||||
newfs_hfs $device
|
||||
mount -t hfs $device $CLAR_TMP
|
||||
fi
|
||||
|
||||
mkdir _build
|
||||
cd _build
|
||||
# shellcheck disable=SC2086
|
||||
cmake .. -DBUILD_EXAMPLES=ON -DCMAKE_INSTALL_PREFIX=../_install $OPTIONS || exit $?
|
||||
make -j2 install || exit $?
|
||||
|
||||
# If this platform doesn't support test execution, bail out now
|
||||
if [ -n "$SKIP_TESTS" ];
|
||||
then
|
||||
exit $?;
|
||||
fi
|
||||
|
||||
# Create a test repo which we can use for the online::push tests
|
||||
mkdir "$HOME"/_temp
|
||||
git init --bare "$HOME"/_temp/test.git
|
||||
git daemon --listen=localhost --export-all --enable=receive-pack --base-path="$HOME"/_temp "$HOME"/_temp 2>/dev/null &
|
||||
export GITTEST_REMOTE_URL="git://localhost/test.git"
|
||||
|
||||
# Run the test suite
|
||||
ctest -V -R libgit2_clar || exit $?
|
||||
|
||||
# Now that we've tested the raw git protocol, let's set up ssh to we
|
||||
# can do the push tests over it
|
||||
|
||||
killall git-daemon
|
||||
|
||||
if [ "$TRAVIS_OS_NAME" = "osx" ]; then
|
||||
echo 'PasswordAuthentication yes' | sudo tee -a /etc/sshd_config
|
||||
fi
|
||||
|
||||
ssh-keygen -t rsa -f ~/.ssh/id_rsa -N "" -q
|
||||
cat ~/.ssh/id_rsa.pub >>~/.ssh/authorized_keys
|
||||
ssh-keyscan -t rsa localhost >>~/.ssh/known_hosts
|
||||
|
||||
# Get the fingerprint for localhost and remove the colons so we can parse it as
|
||||
# a hex number. The Mac version is newer so it has a different output format.
|
||||
if [ "$TRAVIS_OS_NAME" = "osx" ]; then
|
||||
export GITTEST_REMOTE_SSH_FINGERPRINT=$(ssh-keygen -E md5 -F localhost -l | tail -n 1 | cut -d ' ' -f 3 | cut -d : -f2- | tr -d :)
|
||||
else
|
||||
export GITTEST_REMOTE_SSH_FINGERPRINT=$(ssh-keygen -F localhost -l | tail -n 1 | cut -d ' ' -f 2 | tr -d ':')
|
||||
fi
|
||||
|
||||
export GITTEST_REMOTE_URL="ssh://localhost/$HOME/_temp/test.git"
|
||||
export GITTEST_REMOTE_USER=$USER
|
||||
export GITTEST_REMOTE_SSH_KEY="$HOME/.ssh/id_rsa"
|
||||
export GITTEST_REMOTE_SSH_PUBKEY="$HOME/.ssh/id_rsa.pub"
|
||||
export GITTEST_REMOTE_SSH_PASSPHRASE=""
|
||||
|
||||
|
||||
if [ -e ./libgit2_clar ]; then
|
||||
./libgit2_clar -sonline::push -sonline::clone::ssh_cert &&
|
||||
./libgit2_clar -sonline::clone::ssh_with_paths || exit $?
|
||||
if [ "$TRAVIS_OS_NAME" = "linux" ]; then
|
||||
./libgit2_clar -sonline::clone::cred_callback || exit $?
|
||||
fi
|
||||
|
||||
# Use the proxy we started at the beginning
|
||||
export GITTEST_REMOTE_PROXY_URL="http://foo:bar@localhost:8080/"
|
||||
./libgit2_clar -sonline::clone::proxy_credentials_in_url || exit $?
|
||||
export GITTEST_REMOTE_PROXY_URL="http://localhost:8080/"
|
||||
export GITTEST_REMOTE_PROXY_USER="foo"
|
||||
export GITTEST_REMOTE_PROXY_PASS="bar"
|
||||
./libgit2_clar -sonline::clone::proxy_credentials_request || exit $?
|
||||
|
||||
fi
|
||||
|
||||
export GITTEST_REMOTE_URL="https://github.com/libgit2/non-existent"
|
||||
export GITTEST_REMOTE_USER="libgit2test"
|
||||
ctest -V -R libgit2_clar-cred_callback
|
||||
cmake --build . --target install || exit $?
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
set -x
|
||||
|
||||
brew update
|
||||
brew install zlib
|
||||
brew install curl
|
||||
brew install openssl
|
||||
brew install libssh2
|
||||
@@ -442,7 +442,7 @@ int git_commit__parse(void *_commit, git_odb_object *odb_obj)
|
||||
while (eoln < buffer_end && *eoln != '\n')
|
||||
++eoln;
|
||||
|
||||
if (git__prefixcmp(buffer, "encoding ") == 0) {
|
||||
if (git__prefixncmp(buffer, buffer_end - buffer, "encoding ") == 0) {
|
||||
buffer += strlen("encoding ");
|
||||
|
||||
commit->message_encoding = git__strndup(buffer, eoln - buffer);
|
||||
|
||||
@@ -171,7 +171,9 @@ static int commit_quick_parse(
|
||||
buffer--;
|
||||
}
|
||||
|
||||
if ((buffer == committer_start) || (git__strtol64(&commit_time, (char *)(buffer + 1), NULL, 10) < 0))
|
||||
if ((buffer == committer_start) ||
|
||||
(git__strntol64(&commit_time, (char *)(buffer + 1),
|
||||
buffer_end - buffer + 1, NULL, 10) < 0))
|
||||
return commit_error(commit, "cannot parse commit time");
|
||||
|
||||
commit->time = commit_time;
|
||||
|
||||
@@ -1298,7 +1298,7 @@ int git_config_parse_int64(int64_t *out, const char *value)
|
||||
const char *num_end;
|
||||
int64_t num;
|
||||
|
||||
if (!value || git__strtol64(&num, value, &num_end, 0) < 0)
|
||||
if (!value || git__strntol64(&num, value, strlen(value), &num_end, 0) < 0)
|
||||
goto fail_parse;
|
||||
|
||||
switch (*num_end) {
|
||||
|
||||
@@ -328,7 +328,7 @@ int git_curl_stream_new(git_stream **out, const char *host, const char *port)
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((error = git__strtol32(&iport, port, NULL, 10)) < 0) {
|
||||
if ((error = git__strntol32(&iport, port, strlen(port), NULL, 10)) < 0) {
|
||||
git__free(st);
|
||||
return error;
|
||||
}
|
||||
|
||||
@@ -2202,7 +2202,7 @@ static int read_reuc(git_index *index, const char *buffer, size_t size)
|
||||
for (i = 0; i < 3; i++) {
|
||||
int64_t tmp;
|
||||
|
||||
if (git__strtol64(&tmp, buffer, &endptr, 8) < 0 ||
|
||||
if (git__strntol64(&tmp, buffer, size, &endptr, 8) < 0 ||
|
||||
!endptr || endptr == buffer || *endptr ||
|
||||
tmp < 0 || tmp > UINT32_MAX) {
|
||||
index_entry_reuc_free(lost);
|
||||
|
||||
@@ -151,7 +151,7 @@ GIT_INLINE(int) rebase_readint(
|
||||
if ((error = rebase_readfile(asc_out, state_path, filename)) < 0)
|
||||
return error;
|
||||
|
||||
if (git__strtol32(&num, asc_out->ptr, &eol, 10) < 0 || num < 0 || *eol) {
|
||||
if (git__strntol32(&num, asc_out->ptr, asc_out->size, &eol, 10) < 0 || num < 0 || *eol) {
|
||||
giterr_set(GITERR_REBASE, "the file '%s' contains an invalid numeric value", filename);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -127,7 +127,8 @@ static int try_parse_numeric(int *n, const char *curly_braces_content)
|
||||
int32_t content;
|
||||
const char *end_ptr;
|
||||
|
||||
if (git__strtol32(&content, curly_braces_content, &end_ptr, 10) < 0)
|
||||
if (git__strntol32(&content, curly_braces_content, strlen(curly_braces_content),
|
||||
&end_ptr, 10) < 0)
|
||||
return -1;
|
||||
|
||||
if (*end_ptr != '\0')
|
||||
@@ -577,7 +578,7 @@ static int extract_how_many(int *n, const char *spec, size_t *pos)
|
||||
} while (spec[(*pos)] == kind && kind == '~');
|
||||
|
||||
if (git__isdigit(spec[*pos])) {
|
||||
if (git__strtol32(&parsed, spec + *pos, &end_ptr, 10) < 0)
|
||||
if (git__strntol32(&parsed, spec + *pos, strlen(spec + *pos), &end_ptr, 10) < 0)
|
||||
return GIT_EINVALIDSPEC;
|
||||
|
||||
accumulated += (parsed - 1);
|
||||
|
||||
@@ -228,7 +228,8 @@ int git_signature__parse(git_signature *sig, const char **buffer_out,
|
||||
const char *time_start = email_end + 2;
|
||||
const char *time_end;
|
||||
|
||||
if (git__strtol64(&sig->when.time, time_start, &time_end, 10) < 0) {
|
||||
if (git__strntol64(&sig->when.time, time_start,
|
||||
buffer_end - time_start, &time_end, 10) < 0) {
|
||||
git__free(sig->name);
|
||||
git__free(sig->email);
|
||||
sig->name = sig->email = NULL;
|
||||
@@ -243,8 +244,9 @@ int git_signature__parse(git_signature *sig, const char **buffer_out,
|
||||
tz_start = time_end + 1;
|
||||
|
||||
if ((tz_start[0] != '-' && tz_start[0] != '+') ||
|
||||
git__strtol32(&offset, tz_start + 1, &tz_end, 10) < 0) {
|
||||
//malformed timezone, just assume it's zero
|
||||
git__strntol32(&offset, tz_start + 1,
|
||||
buffer_end - tz_start + 1, &tz_end, 10) < 0) {
|
||||
/* malformed timezone, just assume it's zero */
|
||||
offset = 0;
|
||||
}
|
||||
|
||||
|
||||
10
src/tag.c
10
src/tag.c
@@ -70,10 +70,9 @@ static int tag_parse(git_tag *tag, const char *buffer, const char *buffer_end)
|
||||
static const char *tag_types[] = {
|
||||
NULL, "commit\n", "tree\n", "blob\n", "tag\n"
|
||||
};
|
||||
|
||||
unsigned int i;
|
||||
size_t text_len, alloc_len;
|
||||
char *search;
|
||||
const char *search;
|
||||
unsigned int i;
|
||||
|
||||
if (git_oid__parse(&tag->target, &buffer, buffer_end, "object ") < 0)
|
||||
return tag_error("object field invalid");
|
||||
@@ -138,8 +137,9 @@ static int tag_parse(git_tag *tag, const char *buffer, const char *buffer_end)
|
||||
tag->message = NULL;
|
||||
if (buffer < buffer_end) {
|
||||
/* If we're not at the end of the header, search for it */
|
||||
if( *buffer != '\n' ) {
|
||||
search = strstr(buffer, "\n\n");
|
||||
if(*buffer != '\n') {
|
||||
search = git__memmem(buffer, buffer_end - buffer,
|
||||
"\n\n", 2);
|
||||
if (search)
|
||||
buffer = search + 1;
|
||||
else
|
||||
|
||||
@@ -43,6 +43,11 @@ GIT_INLINE(int) git_smart__reset_stream(transport_smart *t, bool close_subtransp
|
||||
t->current_stream = NULL;
|
||||
}
|
||||
|
||||
if (t->url) {
|
||||
git__free(t->url);
|
||||
t->url = NULL;
|
||||
}
|
||||
|
||||
if (close_subtransport &&
|
||||
t->wrapped->close(t->wrapped) < 0)
|
||||
return -1;
|
||||
|
||||
@@ -391,7 +391,7 @@ static int parse_len(size_t *out, const char *line, size_t linelen)
|
||||
}
|
||||
}
|
||||
|
||||
if ((error = git__strtol32(&len, num, &num_end, 16)) < 0)
|
||||
if ((error = git__strntol32(&len, num, PKT_LEN_SIZE, &num_end, 16)) < 0)
|
||||
return error;
|
||||
|
||||
if (len < 0)
|
||||
|
||||
@@ -764,7 +764,8 @@ static int winhttp_connect(
|
||||
t->connection = NULL;
|
||||
|
||||
/* Prepare port */
|
||||
if (git__strtol32(&port, t->connection_data.port, NULL, 10) < 0)
|
||||
if (git__strntol32(&port, t->connection_data.port,
|
||||
strlen(t->connection_data.port), NULL, 10) < 0)
|
||||
return -1;
|
||||
|
||||
/* Prepare host */
|
||||
|
||||
@@ -90,7 +90,7 @@ static int read_tree_internal(git_tree_cache **out,
|
||||
return -1;
|
||||
|
||||
/* Blank-terminated ASCII decimal number of entries in this tree */
|
||||
if (git__strtol32(&count, buffer, &buffer, 10) < 0)
|
||||
if (git__strntol32(&count, buffer, buffer_end - buffer, &buffer, 10) < 0)
|
||||
goto corrupted;
|
||||
|
||||
tree->entry_count = count;
|
||||
@@ -99,7 +99,7 @@ static int read_tree_internal(git_tree_cache **out,
|
||||
goto corrupted;
|
||||
|
||||
/* Number of children of the tree, newline-terminated */
|
||||
if (git__strtol32(&count, buffer, &buffer, 10) < 0 || count < 0)
|
||||
if (git__strntol32(&count, buffer, buffer_end - buffer, &buffer, 10) < 0 || count < 0)
|
||||
goto corrupted;
|
||||
|
||||
tree->children_count = count;
|
||||
|
||||
79
src/util.c
79
src/util.c
@@ -64,12 +64,6 @@ int git_strarray_copy(git_strarray *tgt, const git_strarray *src)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int git__strtol64(int64_t *result, const char *nptr, const char **endptr, int base)
|
||||
{
|
||||
|
||||
return git__strntol64(result, nptr, (size_t)-1, endptr, base);
|
||||
}
|
||||
|
||||
int git__strntol64(int64_t *result, const char *nptr, size_t nptr_len, const char **endptr, int base)
|
||||
{
|
||||
const char *p;
|
||||
@@ -128,10 +122,20 @@ int git__strntol64(int64_t *result, const char *nptr, size_t nptr_len, const cha
|
||||
v = c - 'A' + 10;
|
||||
if (v >= base)
|
||||
break;
|
||||
nn = n * base + (neg ? -v : v);
|
||||
if ((!neg && nn < n) || (neg && nn > n))
|
||||
v = neg ? -v : v;
|
||||
if (n > INT64_MAX / base || n < INT64_MIN / base) {
|
||||
ovfl = 1;
|
||||
n = nn;
|
||||
/* Keep on iterating until the end of this number */
|
||||
continue;
|
||||
}
|
||||
nn = n * base;
|
||||
if ((v > 0 && nn > INT64_MAX - v) ||
|
||||
(v < 0 && nn < INT64_MIN - v)) {
|
||||
ovfl = 1;
|
||||
/* Keep on iterating until the end of this number */
|
||||
continue;
|
||||
}
|
||||
n = nn + v;
|
||||
}
|
||||
|
||||
Return:
|
||||
@@ -152,28 +156,26 @@ Return:
|
||||
return 0;
|
||||
}
|
||||
|
||||
int git__strtol32(int32_t *result, const char *nptr, const char **endptr, int base)
|
||||
{
|
||||
|
||||
return git__strntol32(result, nptr, (size_t)-1, endptr, base);
|
||||
}
|
||||
|
||||
int git__strntol32(int32_t *result, const char *nptr, size_t nptr_len, const char **endptr, int base)
|
||||
{
|
||||
int error;
|
||||
const char *tmp_endptr;
|
||||
int32_t tmp_int;
|
||||
int64_t tmp_long;
|
||||
int error;
|
||||
|
||||
if ((error = git__strntol64(&tmp_long, nptr, nptr_len, endptr, base)) < 0)
|
||||
if ((error = git__strntol64(&tmp_long, nptr, nptr_len, &tmp_endptr, base)) < 0)
|
||||
return error;
|
||||
|
||||
tmp_int = tmp_long & 0xFFFFFFFF;
|
||||
if (tmp_int != tmp_long) {
|
||||
giterr_set(GITERR_INVALID, "failed to convert: '%s' is too large", nptr);
|
||||
int len = tmp_endptr - nptr;
|
||||
giterr_set(GITERR_INVALID, "failed to convert: '%.*s' is too large", len, nptr);
|
||||
return -1;
|
||||
}
|
||||
|
||||
*result = tmp_int;
|
||||
if (endptr)
|
||||
*endptr = tmp_endptr;
|
||||
|
||||
return error;
|
||||
}
|
||||
@@ -351,6 +353,47 @@ size_t git__linenlen(const char *buffer, size_t buffer_len)
|
||||
return nl ? (size_t)(nl - buffer) + 1 : buffer_len;
|
||||
}
|
||||
|
||||
/*
|
||||
* Adapted Not So Naive algorithm from http://www-igm.univ-mlv.fr/~lecroq/string/
|
||||
*/
|
||||
const void * git__memmem(const void *haystack, size_t haystacklen,
|
||||
const void *needle, size_t needlelen)
|
||||
{
|
||||
const char *h, *n;
|
||||
size_t j, k, l;
|
||||
|
||||
if (needlelen > haystacklen || !haystacklen || !needlelen)
|
||||
return NULL;
|
||||
|
||||
h = (const char *) haystack,
|
||||
n = (const char *) needle;
|
||||
|
||||
if (needlelen == 1)
|
||||
return memchr(haystack, *n, haystacklen);
|
||||
|
||||
if (n[0] == n[1]) {
|
||||
k = 2;
|
||||
l = 1;
|
||||
} else {
|
||||
k = 1;
|
||||
l = 2;
|
||||
}
|
||||
|
||||
j = 0;
|
||||
while (j <= haystacklen - needlelen) {
|
||||
if (n[1] != h[j + 1]) {
|
||||
j += k;
|
||||
} else {
|
||||
if (memcmp(n + 2, h + j + 2, needlelen - 2) == 0 &&
|
||||
n[0] == h[j])
|
||||
return h + j;
|
||||
j += l;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void git__hexdump(const char *buffer, size_t len)
|
||||
{
|
||||
static const size_t LINE_WIDTH = 16;
|
||||
|
||||
@@ -263,9 +263,7 @@ GIT_INLINE(int) git__signum(int val)
|
||||
return ((val > 0) - (val < 0));
|
||||
}
|
||||
|
||||
extern int git__strtol32(int32_t *n, const char *buff, const char **end_buf, int base);
|
||||
extern int git__strntol32(int32_t *n, const char *buff, size_t buff_len, const char **end_buf, int base);
|
||||
extern int git__strtol64(int64_t *n, const char *buff, const char **end_buf, int base);
|
||||
extern int git__strntol64(int64_t *n, const char *buff, size_t buff_len, const char **end_buf, int base);
|
||||
|
||||
|
||||
@@ -318,6 +316,9 @@ GIT_INLINE(const void *) git__memrchr(const void *s, int c, size_t n)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
extern const void * git__memmem(const void *haystack, size_t haystacklen,
|
||||
const void *needle, size_t needlelen);
|
||||
|
||||
typedef int (*git__tsort_cmp)(const void *a, const void *b);
|
||||
|
||||
extern void git__tsort(void **dst, size_t size, git__tsort_cmp cmp);
|
||||
|
||||
@@ -1,10 +1,22 @@
|
||||
#include "clar_libgit2.h"
|
||||
#include "buffer.h"
|
||||
|
||||
#if defined(GIT_ARCH_64)
|
||||
#define TOOBIG 0xffffffffffffff00
|
||||
/*
|
||||
* We want to use some ridiculous size that `malloc` will fail with
|
||||
* but that does not otherwise interfere with testing. On Linux, choose
|
||||
* a number that is large enough to fail immediately but small enough
|
||||
* that valgrind doesn't believe it to erroneously be a negative number.
|
||||
* On macOS, choose a number that is large enough to fail immediately
|
||||
* without having libc print warnings to stderr.
|
||||
*/
|
||||
#if defined(GIT_ARCH_64) && defined(__linux__)
|
||||
# define TOOBIG 0x0fffffffffffffff
|
||||
#elif defined(__linux__)
|
||||
# define TOOBIG 0x0fffffff
|
||||
#elif defined(GIT_ARCH_64)
|
||||
# define TOOBIG 0xffffffffffffff00
|
||||
#else
|
||||
#define TOOBIG 0xffffff00
|
||||
# define TOOBIG 0xffffff00
|
||||
#endif
|
||||
|
||||
/**
|
||||
|
||||
@@ -1086,6 +1086,8 @@ void test_checkout_tree__filemode_preserved_in_workdir(void)
|
||||
cl_assert(!GIT_PERMS_IS_EXEC(read_filemode("a/b.txt")));
|
||||
|
||||
git_commit_free(commit);
|
||||
#else
|
||||
cl_skip();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
214
tests/clar.c
214
tests/clar.c
@@ -95,9 +95,6 @@ static const char *
|
||||
fixture_path(const char *base, const char *fixture_name);
|
||||
|
||||
struct clar_error {
|
||||
const char *test;
|
||||
int test_number;
|
||||
const char *suite;
|
||||
const char *file;
|
||||
int line_number;
|
||||
const char *error_msg;
|
||||
@@ -106,11 +103,34 @@ struct clar_error {
|
||||
struct clar_error *next;
|
||||
};
|
||||
|
||||
static struct {
|
||||
int argc;
|
||||
char **argv;
|
||||
struct clar_explicit {
|
||||
size_t suite_idx;
|
||||
const char *filter;
|
||||
|
||||
struct clar_explicit *next;
|
||||
};
|
||||
|
||||
struct clar_report {
|
||||
const char *test;
|
||||
int test_number;
|
||||
const char *suite;
|
||||
|
||||
enum cl_test_status status;
|
||||
|
||||
struct clar_error *errors;
|
||||
struct clar_error *last_error;
|
||||
|
||||
struct clar_report *next;
|
||||
};
|
||||
|
||||
struct clar_summary {
|
||||
const char *filename;
|
||||
FILE *fp;
|
||||
};
|
||||
|
||||
static struct {
|
||||
enum cl_test_status test_status;
|
||||
|
||||
const char *active_test;
|
||||
const char *active_suite;
|
||||
|
||||
@@ -124,8 +144,15 @@ static struct {
|
||||
int exit_on_error;
|
||||
int report_suite_names;
|
||||
|
||||
struct clar_error *errors;
|
||||
struct clar_error *last_error;
|
||||
int write_summary;
|
||||
const char *summary_filename;
|
||||
struct clar_summary *summary;
|
||||
|
||||
struct clar_explicit *explicit;
|
||||
struct clar_explicit *last_explicit;
|
||||
|
||||
struct clar_report *reports;
|
||||
struct clar_report *last_report;
|
||||
|
||||
void (*local_cleanup)(void *);
|
||||
void *local_cleanup_payload;
|
||||
@@ -155,7 +182,7 @@ struct clar_suite {
|
||||
/* From clar_print_*.c */
|
||||
static void clar_print_init(int test_count, int suite_count, const char *suite_names);
|
||||
static void clar_print_shutdown(int test_count, int suite_count, int error_count);
|
||||
static void clar_print_error(int num, const struct clar_error *error);
|
||||
static void clar_print_error(int num, const struct clar_report *report, const struct clar_error *error);
|
||||
static void clar_print_ontest(const char *test_name, int test_number, enum cl_test_status failed);
|
||||
static void clar_print_onsuite(const char *suite_name, int suite_index);
|
||||
static void clar_print_onabort(const char *msg, ...);
|
||||
@@ -164,6 +191,10 @@ static void clar_print_onabort(const char *msg, ...);
|
||||
static void clar_unsandbox(void);
|
||||
static int clar_sandbox(void);
|
||||
|
||||
/* From summary.h */
|
||||
static struct clar_summary *clar_summary_init(const char *filename);
|
||||
static int clar_summary_shutdown(struct clar_summary *fp);
|
||||
|
||||
/* Load the declarations for the test suite */
|
||||
#include "clar.suite"
|
||||
|
||||
@@ -186,21 +217,29 @@ void cl_trace_register(cl_trace_cb *cb, void *payload)
|
||||
|
||||
/* Core test functions */
|
||||
static void
|
||||
clar_report_errors(void)
|
||||
clar_report_errors(struct clar_report *report)
|
||||
{
|
||||
struct clar_error *error;
|
||||
int i = 1;
|
||||
struct clar_error *error, *next;
|
||||
|
||||
error = _clar.errors;
|
||||
while (error != NULL) {
|
||||
next = error->next;
|
||||
clar_print_error(i++, error);
|
||||
free(error->description);
|
||||
free(error);
|
||||
error = next;
|
||||
for (error = report->errors; error; error = error->next)
|
||||
clar_print_error(i++, _clar.last_report, error);
|
||||
}
|
||||
|
||||
static void
|
||||
clar_report_all(void)
|
||||
{
|
||||
struct clar_report *report;
|
||||
struct clar_error *error;
|
||||
int i = 1;
|
||||
|
||||
for (report = _clar.reports; report; report = report->next) {
|
||||
if (report->status != CL_TEST_FAILURE)
|
||||
continue;
|
||||
|
||||
for (error = report->errors; error; error = error->next)
|
||||
clar_print_error(i++, report, error);
|
||||
}
|
||||
|
||||
_clar.errors = _clar.last_error = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -209,7 +248,6 @@ clar_run_test(
|
||||
const struct clar_func *initialize,
|
||||
const struct clar_func *cleanup)
|
||||
{
|
||||
_clar.test_status = CL_TEST_OK;
|
||||
_clar.trampoline_enabled = 1;
|
||||
|
||||
CL_TRACE(CL_TRACE__TEST__BEGIN);
|
||||
@@ -225,6 +263,9 @@ clar_run_test(
|
||||
|
||||
_clar.trampoline_enabled = 0;
|
||||
|
||||
if (_clar.last_report->status == CL_TEST_NOTRUN)
|
||||
_clar.last_report->status = CL_TEST_OK;
|
||||
|
||||
if (_clar.local_cleanup != NULL)
|
||||
_clar.local_cleanup(_clar.local_cleanup_payload);
|
||||
|
||||
@@ -240,9 +281,9 @@ clar_run_test(
|
||||
_clar.local_cleanup_payload = NULL;
|
||||
|
||||
if (_clar.report_errors_only) {
|
||||
clar_report_errors();
|
||||
clar_report_errors(_clar.last_report);
|
||||
} else {
|
||||
clar_print_ontest(test->name, _clar.tests_ran, _clar.test_status);
|
||||
clar_print_ontest(test->name, _clar.tests_ran, _clar.last_report->status);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -251,6 +292,7 @@ clar_run_suite(const struct clar_suite *suite, const char *filter)
|
||||
{
|
||||
const struct clar_func *test = suite->tests;
|
||||
size_t i, matchlen;
|
||||
struct clar_report *report;
|
||||
|
||||
if (!suite->enabled)
|
||||
return;
|
||||
@@ -283,6 +325,21 @@ clar_run_suite(const struct clar_suite *suite, const char *filter)
|
||||
continue;
|
||||
|
||||
_clar.active_test = test[i].name;
|
||||
|
||||
report = calloc(1, sizeof(struct clar_report));
|
||||
report->suite = _clar.active_suite;
|
||||
report->test = _clar.active_test;
|
||||
report->test_number = _clar.tests_ran;
|
||||
report->status = CL_TEST_NOTRUN;
|
||||
|
||||
if (_clar.reports == NULL)
|
||||
_clar.reports = report;
|
||||
|
||||
if (_clar.last_report != NULL)
|
||||
_clar.last_report->next = report;
|
||||
|
||||
_clar.last_report = report;
|
||||
|
||||
clar_run_test(&test[i], &suite->initialize, &suite->cleanup);
|
||||
|
||||
if (_clar.exit_on_error && _clar.total_errors)
|
||||
@@ -298,13 +355,14 @@ clar_usage(const char *arg)
|
||||
{
|
||||
printf("Usage: %s [options]\n\n", arg);
|
||||
printf("Options:\n");
|
||||
printf(" -sname\tRun only the suite with `name` (can go to individual test name)\n");
|
||||
printf(" -iname\tInclude the suite with `name`\n");
|
||||
printf(" -xname\tExclude the suite with `name`\n");
|
||||
printf(" -v \tIncrease verbosity (show suite names)\n");
|
||||
printf(" -q \tOnly report tests that had an error\n");
|
||||
printf(" -Q \tQuit as soon as a test fails\n");
|
||||
printf(" -l \tPrint suite names\n");
|
||||
printf(" -sname Run only the suite with `name` (can go to individual test name)\n");
|
||||
printf(" -iname Include the suite with `name`\n");
|
||||
printf(" -xname Exclude the suite with `name`\n");
|
||||
printf(" -v Increase verbosity (show suite names)\n");
|
||||
printf(" -q Only report tests that had an error\n");
|
||||
printf(" -Q Quit as soon as a test fails\n");
|
||||
printf(" -l Print suite names\n");
|
||||
printf(" -r[filename] Write summary file (to the optional filename)\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
@@ -313,11 +371,18 @@ clar_parse_args(int argc, char **argv)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* Verify options before execute */
|
||||
for (i = 1; i < argc; ++i) {
|
||||
char *argument = argv[i];
|
||||
|
||||
if (argument[0] != '-')
|
||||
if (argument[0] != '-' || argument[1] == '\0'
|
||||
|| strchr("sixvqQlr", argument[1]) == NULL) {
|
||||
clar_usage(argv[0]);
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 1; i < argc; ++i) {
|
||||
char *argument = argv[i];
|
||||
|
||||
switch (argument[1]) {
|
||||
case 's':
|
||||
@@ -352,7 +417,24 @@ clar_parse_args(int argc, char **argv)
|
||||
_clar.report_suite_names = 1;
|
||||
|
||||
switch (action) {
|
||||
case 's': _clar_suites[j].enabled = 1; clar_run_suite(&_clar_suites[j], argument); break;
|
||||
case 's': {
|
||||
struct clar_explicit *explicit =
|
||||
calloc(1, sizeof(struct clar_explicit));
|
||||
assert(explicit);
|
||||
|
||||
explicit->suite_idx = j;
|
||||
explicit->filter = argument;
|
||||
|
||||
if (_clar.explicit == NULL)
|
||||
_clar.explicit = explicit;
|
||||
|
||||
if (_clar.last_explicit != NULL)
|
||||
_clar.last_explicit->next = explicit;
|
||||
|
||||
_clar_suites[j].enabled = 1;
|
||||
_clar.last_explicit = explicit;
|
||||
break;
|
||||
}
|
||||
case 'i': _clar_suites[j].enabled = 1; break;
|
||||
case 'x': _clar_suites[j].enabled = 0; break;
|
||||
}
|
||||
@@ -390,8 +472,14 @@ clar_parse_args(int argc, char **argv)
|
||||
_clar.report_suite_names = 1;
|
||||
break;
|
||||
|
||||
case 'r':
|
||||
_clar.write_summary = 1;
|
||||
_clar.summary_filename = *(argument + 2) ? (argument + 2) :
|
||||
"summary.xml";
|
||||
break;
|
||||
|
||||
default:
|
||||
clar_usage(argv[0]);
|
||||
assert(!"Unexpected commandline argument!");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -405,23 +493,31 @@ clar_test_init(int argc, char **argv)
|
||||
""
|
||||
);
|
||||
|
||||
if (argc > 1)
|
||||
clar_parse_args(argc, argv);
|
||||
|
||||
if (_clar.write_summary &&
|
||||
!(_clar.summary = clar_summary_init(_clar.summary_filename))) {
|
||||
clar_print_onabort("Failed to open the summary file\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
if (clar_sandbox() < 0) {
|
||||
clar_print_onabort("Failed to sandbox the test runner.\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
_clar.argc = argc;
|
||||
_clar.argv = argv;
|
||||
}
|
||||
|
||||
int
|
||||
clar_test_run(void)
|
||||
{
|
||||
if (_clar.argc > 1)
|
||||
clar_parse_args(_clar.argc, _clar.argv);
|
||||
size_t i;
|
||||
struct clar_explicit *explicit;
|
||||
|
||||
if (!_clar.suites_ran) {
|
||||
size_t i;
|
||||
if (_clar.explicit) {
|
||||
for (explicit = _clar.explicit; explicit; explicit = explicit->next)
|
||||
clar_run_suite(&_clar_suites[explicit->suite_idx], explicit->filter);
|
||||
} else {
|
||||
for (i = 0; i < _clar_suite_count; ++i)
|
||||
clar_run_suite(&_clar_suites[i], NULL);
|
||||
}
|
||||
@@ -432,6 +528,9 @@ clar_test_run(void)
|
||||
void
|
||||
clar_test_shutdown(void)
|
||||
{
|
||||
struct clar_explicit *explicit, *explicit_next;
|
||||
struct clar_report *report, *report_next;
|
||||
|
||||
clar_print_shutdown(
|
||||
_clar.tests_ran,
|
||||
(int)_clar_suite_count,
|
||||
@@ -439,6 +538,21 @@ clar_test_shutdown(void)
|
||||
);
|
||||
|
||||
clar_unsandbox();
|
||||
|
||||
if (_clar.write_summary && clar_summary_shutdown(_clar.summary) < 0) {
|
||||
clar_print_onabort("Failed to write the summary file\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
for (explicit = _clar.explicit; explicit; explicit = explicit_next) {
|
||||
explicit_next = explicit->next;
|
||||
free(explicit);
|
||||
}
|
||||
|
||||
for (report = _clar.reports; report; report = report_next) {
|
||||
report_next = report->next;
|
||||
free(report);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
@@ -458,7 +572,7 @@ static void abort_test(void)
|
||||
if (!_clar.trampoline_enabled) {
|
||||
clar_print_onabort(
|
||||
"Fatal error: a cleanup method raised an exception.");
|
||||
clar_report_errors();
|
||||
clar_report_errors(_clar.last_report);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
@@ -468,7 +582,7 @@ static void abort_test(void)
|
||||
|
||||
void clar__skip(void)
|
||||
{
|
||||
_clar.test_status = CL_TEST_SKIP;
|
||||
_clar.last_report->status = CL_TEST_SKIP;
|
||||
_clar.total_skipped++;
|
||||
abort_test();
|
||||
}
|
||||
@@ -482,17 +596,14 @@ void clar__fail(
|
||||
{
|
||||
struct clar_error *error = calloc(1, sizeof(struct clar_error));
|
||||
|
||||
if (_clar.errors == NULL)
|
||||
_clar.errors = error;
|
||||
if (_clar.last_report->errors == NULL)
|
||||
_clar.last_report->errors = error;
|
||||
|
||||
if (_clar.last_error != NULL)
|
||||
_clar.last_error->next = error;
|
||||
if (_clar.last_report->last_error != NULL)
|
||||
_clar.last_report->last_error->next = error;
|
||||
|
||||
_clar.last_error = error;
|
||||
_clar.last_report->last_error = error;
|
||||
|
||||
error->test = _clar.active_test;
|
||||
error->test_number = _clar.tests_ran;
|
||||
error->suite = _clar.active_suite;
|
||||
error->file = file;
|
||||
error->line_number = line;
|
||||
error->error_msg = error_msg;
|
||||
@@ -501,7 +612,7 @@ void clar__fail(
|
||||
error->description = strdup(description);
|
||||
|
||||
_clar.total_errors++;
|
||||
_clar.test_status = CL_TEST_FAILURE;
|
||||
_clar.last_report->status = CL_TEST_FAILURE;
|
||||
|
||||
if (should_abort)
|
||||
abort_test();
|
||||
@@ -646,3 +757,4 @@ void cl_set_cleanup(void (*cleanup)(void *), void *opaque)
|
||||
#include "clar/fixtures.h"
|
||||
#include "clar/fs.h"
|
||||
#include "clar/print.h"
|
||||
#include "clar/summary.h"
|
||||
|
||||
@@ -12,13 +12,16 @@
|
||||
enum cl_test_status {
|
||||
CL_TEST_OK,
|
||||
CL_TEST_FAILURE,
|
||||
CL_TEST_SKIP
|
||||
CL_TEST_SKIP,
|
||||
CL_TEST_NOTRUN,
|
||||
};
|
||||
|
||||
/** Setup clar environment */
|
||||
void clar_test_init(int argc, char *argv[]);
|
||||
int clar_test_run(void);
|
||||
void clar_test_shutdown(void);
|
||||
|
||||
/** One shot setup & run */
|
||||
int clar_test(int argc, char *argv[]);
|
||||
|
||||
const char *clar_sandbox_path(void);
|
||||
|
||||
@@ -13,16 +13,16 @@ static void clar_print_shutdown(int test_count, int suite_count, int error_count
|
||||
(void)error_count;
|
||||
|
||||
printf("\n\n");
|
||||
clar_report_errors();
|
||||
clar_report_all();
|
||||
}
|
||||
|
||||
static void clar_print_error(int num, const struct clar_error *error)
|
||||
static void clar_print_error(int num, const struct clar_report *report, const struct clar_error *error)
|
||||
{
|
||||
printf(" %d) Failure:\n", num);
|
||||
|
||||
printf("%s::%s [%s:%d]\n",
|
||||
error->suite,
|
||||
error->test,
|
||||
report->suite,
|
||||
report->test,
|
||||
error->file,
|
||||
error->line_number);
|
||||
|
||||
@@ -44,6 +44,7 @@ static void clar_print_ontest(const char *test_name, int test_number, enum cl_te
|
||||
case CL_TEST_OK: printf("."); break;
|
||||
case CL_TEST_FAILURE: printf("F"); break;
|
||||
case CL_TEST_SKIP: printf("S"); break;
|
||||
case CL_TEST_NOTRUN: printf("N"); break;
|
||||
}
|
||||
|
||||
fflush(stdout);
|
||||
|
||||
134
tests/clar/summary.h
Normal file
134
tests/clar/summary.h
Normal file
@@ -0,0 +1,134 @@
|
||||
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
|
||||
int clar_summary_close_tag(
|
||||
struct clar_summary *summary, const char *tag, int indent)
|
||||
{
|
||||
const char *indt;
|
||||
|
||||
if (indent == 0) indt = "";
|
||||
else if (indent == 1) indt = "\t";
|
||||
else indt = "\t\t";
|
||||
|
||||
return fprintf(summary->fp, "%s</%s>\n", indt, tag);
|
||||
}
|
||||
|
||||
int clar_summary_testsuites(struct clar_summary *summary)
|
||||
{
|
||||
return fprintf(summary->fp, "<testsuites>\n");
|
||||
}
|
||||
|
||||
int clar_summary_testsuite(struct clar_summary *summary,
|
||||
int idn, const char *name, const char *pkg, time_t timestamp,
|
||||
double elapsed, int test_count, int fail_count, int error_count)
|
||||
{
|
||||
struct tm *tm = localtime(×tamp);
|
||||
char iso_dt[20];
|
||||
|
||||
if (strftime(iso_dt, sizeof(iso_dt), "%Y-%m-%dT%H:%M:%S", tm) == 0)
|
||||
return -1;
|
||||
|
||||
return fprintf(summary->fp, "\t<testsuite "
|
||||
" id=\"%d\""
|
||||
" name=\"%s\""
|
||||
" package=\"%s\""
|
||||
" hostname=\"localhost\""
|
||||
" timestamp=\"%s\""
|
||||
" time=\"%.2f\""
|
||||
" tests=\"%d\""
|
||||
" failures=\"%d\""
|
||||
" errors=\"%d\">\n",
|
||||
idn, name, pkg, iso_dt, elapsed, test_count, fail_count, error_count);
|
||||
}
|
||||
|
||||
int clar_summary_testcase(struct clar_summary *summary,
|
||||
const char *name, const char *classname, double elapsed)
|
||||
{
|
||||
return fprintf(summary->fp,
|
||||
"\t\t<testcase name=\"%s\" classname=\"%s\" time=\"%.2f\">\n",
|
||||
name, classname, elapsed);
|
||||
}
|
||||
|
||||
int clar_summary_failure(struct clar_summary *summary,
|
||||
const char *type, const char *message, const char *desc)
|
||||
{
|
||||
return fprintf(summary->fp,
|
||||
"\t\t\t<failure type=\"%s\"><![CDATA[%s\n%s]]></failure>\n",
|
||||
type, message, desc);
|
||||
}
|
||||
|
||||
struct clar_summary *clar_summary_init(const char *filename)
|
||||
{
|
||||
struct clar_summary *summary;
|
||||
FILE *fp;
|
||||
|
||||
if ((fp = fopen(filename, "w")) == NULL)
|
||||
return NULL;
|
||||
|
||||
if ((summary = malloc(sizeof(struct clar_summary))) == NULL) {
|
||||
fclose(fp);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
summary->filename = filename;
|
||||
summary->fp = fp;
|
||||
|
||||
return summary;
|
||||
}
|
||||
|
||||
int clar_summary_shutdown(struct clar_summary *summary)
|
||||
{
|
||||
struct clar_report *report;
|
||||
const char *last_suite = NULL;
|
||||
|
||||
if (clar_summary_testsuites(summary) < 0)
|
||||
goto on_error;
|
||||
|
||||
report = _clar.reports;
|
||||
while (report != NULL) {
|
||||
struct clar_error *error = report->errors;
|
||||
|
||||
if (last_suite == NULL || strcmp(last_suite, report->suite) != 0) {
|
||||
if (clar_summary_testsuite(summary, 0, report->suite, "",
|
||||
time(NULL), 0, _clar.tests_ran, _clar.total_errors, 0) < 0)
|
||||
goto on_error;
|
||||
}
|
||||
|
||||
last_suite = report->suite;
|
||||
|
||||
clar_summary_testcase(summary, report->test, "what", 0);
|
||||
|
||||
while (error != NULL) {
|
||||
if (clar_summary_failure(summary, "assert",
|
||||
error->error_msg, error->description) < 0)
|
||||
goto on_error;
|
||||
|
||||
error = error->next;
|
||||
}
|
||||
|
||||
if (clar_summary_close_tag(summary, "testcase", 2) < 0)
|
||||
goto on_error;
|
||||
|
||||
report = report->next;
|
||||
|
||||
if (!report || strcmp(last_suite, report->suite) != 0) {
|
||||
if (clar_summary_close_tag(summary, "testsuite", 1) < 0)
|
||||
goto on_error;
|
||||
}
|
||||
}
|
||||
|
||||
if (clar_summary_close_tag(summary, "testsuites", 0) < 0 ||
|
||||
fclose(summary->fp) != 0)
|
||||
goto on_error;
|
||||
|
||||
printf("written summary file to %s\n", summary->filename);
|
||||
|
||||
free(summary);
|
||||
return 0;
|
||||
|
||||
on_error:
|
||||
fclose(summary->fp);
|
||||
free(summary);
|
||||
return -1;
|
||||
}
|
||||
46
tests/core/memmem.c
Normal file
46
tests/core/memmem.c
Normal file
@@ -0,0 +1,46 @@
|
||||
#include "clar_libgit2.h"
|
||||
|
||||
static void assert_found(const char *haystack, const char *needle, size_t expected_pos)
|
||||
{
|
||||
cl_assert_equal_p(git__memmem(haystack, haystack ? strlen(haystack) : 0,
|
||||
needle, needle ? strlen(needle) : 0),
|
||||
haystack + expected_pos);
|
||||
}
|
||||
|
||||
static void assert_absent(const char *haystack, const char *needle)
|
||||
{
|
||||
cl_assert_equal_p(git__memmem(haystack, haystack ? strlen(haystack) : 0,
|
||||
needle, needle ? strlen(needle) : 0),
|
||||
NULL);
|
||||
}
|
||||
|
||||
void test_core_memmem__found(void)
|
||||
{
|
||||
assert_found("a", "a", 0);
|
||||
assert_found("ab", "a", 0);
|
||||
assert_found("ba", "a", 1);
|
||||
assert_found("aa", "a", 0);
|
||||
assert_found("aab", "aa", 0);
|
||||
assert_found("baa", "aa", 1);
|
||||
assert_found("dabc", "abc", 1);
|
||||
assert_found("abababc", "abc", 4);
|
||||
}
|
||||
|
||||
void test_core_memmem__absent(void)
|
||||
{
|
||||
assert_absent("a", "b");
|
||||
assert_absent("a", "aa");
|
||||
assert_absent("ba", "ab");
|
||||
assert_absent("ba", "ab");
|
||||
assert_absent("abc", "abcd");
|
||||
assert_absent("abcabcabc", "bcac");
|
||||
}
|
||||
|
||||
void test_core_memmem__edgecases(void)
|
||||
{
|
||||
assert_absent(NULL, NULL);
|
||||
assert_absent("a", NULL);
|
||||
assert_absent(NULL, "a");
|
||||
assert_absent("", "a");
|
||||
assert_absent("a", "");
|
||||
}
|
||||
@@ -1,45 +1,84 @@
|
||||
#include "clar_libgit2.h"
|
||||
|
||||
static void assert_l32_parses(const char *string, int32_t expected, int base)
|
||||
{
|
||||
int32_t i;
|
||||
cl_git_pass(git__strntol32(&i, string, strlen(string), NULL, base));
|
||||
cl_assert_equal_i(i, expected);
|
||||
}
|
||||
|
||||
static void assert_l32_fails(const char *string, int base)
|
||||
{
|
||||
int32_t i;
|
||||
cl_git_fail(git__strntol32(&i, string, strlen(string), NULL, base));
|
||||
}
|
||||
|
||||
static void assert_l64_parses(const char *string, int64_t expected, int base)
|
||||
{
|
||||
int64_t i;
|
||||
cl_git_pass(git__strntol64(&i, string, strlen(string), NULL, base));
|
||||
cl_assert_equal_i(i, expected);
|
||||
}
|
||||
|
||||
static void assert_l64_fails(const char *string, int base)
|
||||
{
|
||||
int64_t i;
|
||||
cl_git_fail(git__strntol64(&i, string, strlen(string), NULL, base));
|
||||
}
|
||||
|
||||
void test_core_strtol__int32(void)
|
||||
{
|
||||
int32_t i;
|
||||
assert_l32_parses("123", 123, 10);
|
||||
assert_l32_parses(" +123 ", 123, 10);
|
||||
assert_l32_parses(" +2147483647 ", 2147483647, 10);
|
||||
assert_l32_parses(" -2147483648 ", -2147483648LL, 10);
|
||||
assert_l32_parses("A", 10, 16);
|
||||
assert_l32_parses("1x1", 1, 10);
|
||||
|
||||
cl_git_pass(git__strtol32(&i, "123", NULL, 10));
|
||||
cl_assert(i == 123);
|
||||
cl_git_pass(git__strtol32(&i, " +123 ", NULL, 10));
|
||||
cl_assert(i == 123);
|
||||
cl_git_pass(git__strtol32(&i, " +2147483647 ", NULL, 10));
|
||||
cl_assert(i == 2147483647);
|
||||
cl_git_pass(git__strtol32(&i, " -2147483648 ", NULL, 10));
|
||||
cl_assert(i == -2147483648LL);
|
||||
|
||||
cl_git_fail(git__strtol32(&i, " 2147483657 ", NULL, 10));
|
||||
cl_git_fail(git__strtol32(&i, " -2147483657 ", NULL, 10));
|
||||
assert_l32_fails("", 10);
|
||||
assert_l32_fails("a", 10);
|
||||
assert_l32_fails("x10x", 10);
|
||||
assert_l32_fails(" 2147483657 ", 10);
|
||||
assert_l32_fails(" -2147483657 ", 10);
|
||||
}
|
||||
|
||||
void test_core_strtol__int64(void)
|
||||
{
|
||||
int64_t i;
|
||||
assert_l64_parses("123", 123, 10);
|
||||
assert_l64_parses(" +123 ", 123, 10);
|
||||
assert_l64_parses(" +2147483647 ", 2147483647, 10);
|
||||
assert_l64_parses(" -2147483648 ", -2147483648LL, 10);
|
||||
assert_l64_parses(" 2147483657 ", 2147483657LL, 10);
|
||||
assert_l64_parses(" -2147483657 ", -2147483657LL, 10);
|
||||
assert_l64_parses(" 9223372036854775807 ", INT64_MAX, 10);
|
||||
assert_l64_parses(" -9223372036854775808 ", INT64_MIN, 10);
|
||||
assert_l64_parses(" 0x7fffffffffffffff ", INT64_MAX, 16);
|
||||
assert_l64_parses(" -0x8000000000000000 ", INT64_MIN, 16);
|
||||
assert_l64_parses("1a", 26, 16);
|
||||
assert_l64_parses("1A", 26, 16);
|
||||
|
||||
cl_git_pass(git__strtol64(&i, "123", NULL, 10));
|
||||
cl_assert(i == 123);
|
||||
cl_git_pass(git__strtol64(&i, " +123 ", NULL, 10));
|
||||
cl_assert(i == 123);
|
||||
cl_git_pass(git__strtol64(&i, " +2147483647 ", NULL, 10));
|
||||
cl_assert(i == 2147483647);
|
||||
cl_git_pass(git__strtol64(&i, " -2147483648 ", NULL, 10));
|
||||
cl_assert(i == -2147483648LL);
|
||||
cl_git_pass(git__strtol64(&i, " 2147483657 ", NULL, 10));
|
||||
cl_assert(i == 2147483657LL);
|
||||
cl_git_pass(git__strtol64(&i, " -2147483657 ", NULL, 10));
|
||||
cl_assert(i == -2147483657LL);
|
||||
cl_git_pass(git__strtol64(&i, " 9223372036854775807 ", NULL, 10));
|
||||
cl_assert(i == INT64_MAX);
|
||||
cl_git_pass(git__strtol64(&i, " -9223372036854775808 ", NULL, 10));
|
||||
cl_assert(i == INT64_MIN);
|
||||
cl_git_pass(git__strtol64(&i, " 0x7fffffffffffffff ", NULL, 16));
|
||||
cl_assert(i == INT64_MAX);
|
||||
cl_git_pass(git__strtol64(&i, " -0x8000000000000000 ", NULL, 16));
|
||||
cl_assert(i == INT64_MIN);
|
||||
assert_l64_fails("", 10);
|
||||
assert_l64_fails("a", 10);
|
||||
assert_l64_fails("x10x", 10);
|
||||
assert_l64_fails("0x8000000000000000", 16);
|
||||
assert_l64_fails("-0x8000000000000001", 16);
|
||||
}
|
||||
|
||||
void test_core_strtol__buffer_length_truncates(void)
|
||||
{
|
||||
int32_t i32;
|
||||
int64_t i64;
|
||||
|
||||
cl_git_pass(git__strntol32(&i32, "11", 1, NULL, 10));
|
||||
cl_assert_equal_i(i32, 1);
|
||||
|
||||
cl_git_pass(git__strntol64(&i64, "11", 1, NULL, 10));
|
||||
cl_assert_equal_i(i64, 1);
|
||||
}
|
||||
|
||||
void test_core_strtol__error_message_cuts_off(void)
|
||||
{
|
||||
assert_l32_fails("2147483657foobar", 10);
|
||||
cl_assert(strstr(giterr_last()->message, "2147483657") != NULL);
|
||||
cl_assert(strstr(giterr_last()->message, "foobar") == NULL);
|
||||
}
|
||||
|
||||
@@ -51,8 +51,7 @@ void expect_iterator_items(
|
||||
cl_assert(entry->mode != GIT_FILEMODE_TREE);
|
||||
}
|
||||
|
||||
if (++count >= expected_flat)
|
||||
break;
|
||||
cl_assert(++count <= expected_flat);
|
||||
}
|
||||
|
||||
assert_at_end(i, v);
|
||||
|
||||
@@ -662,7 +662,7 @@ void test_iterator_workdir__filesystem_gunk(void)
|
||||
/* should only have 13 items, since we're not asking for trees to be
|
||||
* returned. the goal of this test is simply to not crash.
|
||||
*/
|
||||
expect_iterator_items(i, 13, NULL, 13, NULL);
|
||||
expect_iterator_items(i, 15, NULL, 15, NULL);
|
||||
git_iterator_free(i);
|
||||
git_buf_free(&parent);
|
||||
}
|
||||
@@ -741,6 +741,8 @@ void test_iterator_workdir__skips_fifos_and_special_files(void)
|
||||
cl_assert_equal_i(GIT_ITEROVER, git_iterator_advance(&e, i));
|
||||
|
||||
git_iterator_free(i);
|
||||
#else
|
||||
cl_skip();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -263,8 +263,11 @@ static int cred_failure_cb(
|
||||
|
||||
void test_online_clone__cred_callback_failure_return_code_is_tunnelled(void)
|
||||
{
|
||||
if (!_remote_url || !_remote_user)
|
||||
clar__skip();
|
||||
git__free(_remote_url);
|
||||
git__free(_remote_user);
|
||||
|
||||
_remote_url = git__strdup("https://github.com/libgit2/non-existent");
|
||||
_remote_user = git__strdup("libgit2test");
|
||||
|
||||
g_options.fetch_opts.callbacks.credentials = cred_failure_cb;
|
||||
|
||||
@@ -293,8 +296,11 @@ void test_online_clone__cred_callback_called_again_on_auth_failure(void)
|
||||
{
|
||||
size_t counter = 0;
|
||||
|
||||
if (!_remote_url || !_remote_user)
|
||||
clar__skip();
|
||||
git__free(_remote_url);
|
||||
git__free(_remote_user);
|
||||
|
||||
_remote_url = git__strdup("https://github.com/libgit2/non-existent");
|
||||
_remote_user = git__strdup("libgit2test");
|
||||
|
||||
g_options.fetch_opts.callbacks.credentials = cred_count_calls_cb;
|
||||
g_options.fetch_opts.callbacks.payload = &counter;
|
||||
@@ -577,7 +583,7 @@ void test_online_clone__ssh_cert(void)
|
||||
if (!_remote_ssh_fingerprint)
|
||||
cl_skip();
|
||||
|
||||
cl_git_fail_with(GIT_EUSER, git_clone(&g_repo, "ssh://localhost/foo", "./foo", &g_options));
|
||||
cl_git_fail_with(GIT_EUSER, git_clone(&g_repo, _remote_url, "./foo", &g_options));
|
||||
}
|
||||
|
||||
static char *read_key_file(const char *path)
|
||||
@@ -707,25 +713,37 @@ static int proxy_creds(git_cred **out, const char *url, const char *username, un
|
||||
|
||||
void test_online_clone__proxy_credentials_request(void)
|
||||
{
|
||||
git_buf url = GIT_BUF_INIT;
|
||||
|
||||
if (!_remote_proxy_url || !_remote_proxy_user || !_remote_proxy_pass)
|
||||
cl_skip();
|
||||
|
||||
cl_git_pass(git_buf_printf(&url, "http://%s/", _remote_proxy_url));
|
||||
|
||||
g_options.fetch_opts.proxy_opts.type = GIT_PROXY_SPECIFIED;
|
||||
g_options.fetch_opts.proxy_opts.url = _remote_proxy_url;
|
||||
g_options.fetch_opts.proxy_opts.url = url.ptr;
|
||||
g_options.fetch_opts.proxy_opts.credentials = proxy_creds;
|
||||
called_proxy_creds = 0;
|
||||
cl_git_pass(git_clone(&g_repo, "http://github.com/libgit2/TestGitRepository", "./foo", &g_options));
|
||||
cl_assert(called_proxy_creds);
|
||||
|
||||
git_buf_free(&url);
|
||||
}
|
||||
|
||||
void test_online_clone__proxy_credentials_in_url(void)
|
||||
{
|
||||
if (!_remote_proxy_url)
|
||||
git_buf url = GIT_BUF_INIT;
|
||||
|
||||
if (!_remote_proxy_url || !_remote_proxy_user || !_remote_proxy_pass)
|
||||
cl_skip();
|
||||
|
||||
cl_git_pass(git_buf_printf(&url, "http://%s:%s@%s/", _remote_proxy_user, _remote_proxy_pass, _remote_proxy_url));
|
||||
|
||||
g_options.fetch_opts.proxy_opts.type = GIT_PROXY_SPECIFIED;
|
||||
g_options.fetch_opts.proxy_opts.url = _remote_proxy_url;
|
||||
g_options.fetch_opts.proxy_opts.url = url.ptr;
|
||||
called_proxy_creds = 0;
|
||||
cl_git_pass(git_clone(&g_repo, "http://github.com/libgit2/TestGitRepository", "./foo", &g_options));
|
||||
cl_assert(called_proxy_creds == 0);
|
||||
|
||||
git_buf_free(&url);
|
||||
}
|
||||
|
||||
@@ -152,8 +152,12 @@ static void do_verify_push_status(record_callbacks_data *data, const push_status
|
||||
git_buf_free(&msg);
|
||||
}
|
||||
|
||||
git_vector_foreach(actual, i, iter)
|
||||
git__free(iter);
|
||||
git_vector_foreach(actual, i, iter) {
|
||||
push_status *s = (push_status *)iter;
|
||||
git__free(s->ref);
|
||||
git__free(s->msg);
|
||||
git__free(s);
|
||||
}
|
||||
|
||||
git_vector_free(actual);
|
||||
}
|
||||
@@ -393,7 +397,7 @@ void test_online_push__initialize(void)
|
||||
}
|
||||
|
||||
git_remote_disconnect(_remote);
|
||||
git_vector_free(&delete_specs);
|
||||
git_vector_free_deep(&delete_specs);
|
||||
|
||||
/* Now that we've deleted everything, fetch from the remote */
|
||||
memcpy(&fetch_opts.callbacks, &_record_cbs, sizeof(git_remote_callbacks));
|
||||
|
||||
@@ -25,20 +25,7 @@
|
||||
#define ID_BRANCH_A "d853fb9f24e0fe63b3dce9fbc04fd9cfe17a030b"
|
||||
#define ID_BRANCH_B "1ce9ea3ba9b4fa666602d52a5281d41a482cc58b"
|
||||
|
||||
|
||||
void test_perf_merge__initialize(void)
|
||||
{
|
||||
}
|
||||
|
||||
void test_perf_merge__cleanup(void)
|
||||
{
|
||||
}
|
||||
|
||||
void test_perf_merge__m1(void)
|
||||
{
|
||||
#if 1
|
||||
cl_skip();
|
||||
#else
|
||||
perf__do_merge(SRC_REPO, "m1", ID_BRANCH_A, ID_BRANCH_B);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -180,6 +180,8 @@ void test_repo_open__from_git_new_workdir(void)
|
||||
cl_assert_(git__suffixcmp(git_repository_workdir(repo2), "alternate/") == 0, git_repository_workdir(repo2));
|
||||
|
||||
git_repository_free(repo2);
|
||||
#else
|
||||
cl_skip();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -1072,6 +1072,8 @@ void test_status_worktree__unreadable(void)
|
||||
cl_assert_equal_i(counts.expected_entry_count, counts.entry_count);
|
||||
cl_assert_equal_i(0, counts.wrong_status_flags_count);
|
||||
cl_assert_equal_i(0, counts.wrong_sorted_path);
|
||||
#else
|
||||
cl_skip();
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -1106,6 +1108,8 @@ void test_status_worktree__unreadable_not_included(void)
|
||||
cl_assert_equal_i(counts.expected_entry_count, counts.entry_count);
|
||||
cl_assert_equal_i(0, counts.wrong_status_flags_count);
|
||||
cl_assert_equal_i(0, counts.wrong_sorted_path);
|
||||
#else
|
||||
cl_skip();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user