git2go
git2go copied to clipboard
Libgit2 return not wanted error: libgit2 was not built with OpenSSL support
When you run following code:
func TestLibGit2InitError(t *testing.T) {
// the more time pass, the possibility of openssl init error occurrence is smaller, because something cleans it
time.Sleep(3 * time.Microsecond)
//if sleep is set to less than 3 um, then we have a high possibility of noticid git openssl init error
gitErr := git2go.MakeGitError2(int(git2go.ErrorCodeNotFound))
fmt.Println(gitErr)
}
Git2go sometimes return correct error, sometimes return "libgit2 was not built with OpenSSL support". It depends on sleep duration.
I have got the same results with following versions:
- libgit2-dev libgit2-1.1/now 1.1.0+dfsg.1-4 amd64 [installed,local]
- libgit2-dev/experimental,now 1.3.0+dfsg.1-1 amd64 [installed]
I found that following code is executed: https://github.com/libgit2/libgit2/blob/main/src/streams/openssl.c#L741
package git
import (
"fmt"
"testing"
"time"
"github.com/libgit2/git2go/v33"
)
// MakeGitError2 mimics the git2go error creation function (adjust to match your codebase).
func MakeGitError2(code int) error {
return git2go.NewError(git2go.ErrorCode(code))
}
// initLibgit2 ensures libgit2 is initialized and OpenSSL is ready.
func initLibgit2() error {
if err := git2go.Init(); err != nil {
return fmt.Errorf("failed to initialize libgit2: %v", err)
}
return nil
}
func TestLibGit2InitError(t *testing.T) {
// Ensure libgit2 is initialized
if err := initLibgit2(); err != nil {
t.Fatalf("initLibgit2 failed: %v", err)
}
defer git2go.Shutdown()
// Test with different sleep durations
for _, sleepDuration := range []time.Duration{
1 * time.Microsecond,
3 * time.Microsecond,
10 * time.Microsecond,
} {
t.Run(fmt.Sprintf("Sleep_%v", sleepDuration), func(t *testing.T) {
// Simulate race condition with sleep
time.Sleep(sleepDuration)
// Create error
gitErr := MakeGitError2(int(git2go.ErrorCodeNotFound))
fmt.Println(gitErr)
// Check if the error is the expected NotFound or an OpenSSL error
if gitErr.Error() == "libgit2 was not built with OpenSSL support" {
t.Errorf("unexpected OpenSSL error with sleep %v", sleepDuration)
}
})
}
}
// Workaround: Force OpenSSL initialization before tests
func TestWithForcedOpenSSLInit(t *testing.T) {
// Explicitly initialize libgit2 and force OpenSSL stream registration
if err := initLibgit2(); err != nil {
t.Fatalf("initLibgit2 failed: %v", err)
}
// Force OpenSSL stream initialization (mimics git_stream_register_tls)
// This requires a custom cgo call to ensure OpenSSL is ready
if err := forceOpenSSLStreamInit(); err != nil {
t.Fatalf("forceOpenSSLStreamInit failed: %v", err)
}
defer git2go.Shutdown()
// Test with minimal sleep
time.Sleep(1 * time.Microsecond)
gitErr := MakeGitError2(int(git2go.ErrorCodeNotFound))
fmt.Println(gitErr)
if gitErr.Error() == "libgit2 was not built with OpenSSL support" {
t.Error("unexpected OpenSSL error even with forced initialization")
}
}
// forceOpenSSLStreamInit calls libgit2's OpenSSL stream initialization explicitly.
func forceOpenSSLStreamInit() error {
// Using cgo to call git_stream_register_tls (adjust to your libgit2 version)
// #cgo pkg-config: libgit2
// #include <git2.h>
// int init_openssl_streams() {
// return git_stream_register_tls();
// }
import "C"
ret := C.init_openssl_streams()
if ret != 0 {
return fmt.Errorf("failed to register OpenSSL streams: %s", git2go.NewError(git2go.ErrorCode(ret)).Error())
}
return nil
}