ronantakizawa/codereview-bench huggingface dataset:
Repository: SerenityOS/serenity
File: Userland/Services/SystemServer/Service.cpp (C++)

Code before:
    VERIFY(!m_multi_instance || !m_keep_alive);
}

ErrorOr<NonnullRefPtr<Service>> Service::try_create(Core::ConfigFile const& config, StringView name)
{
    return TRY(adopt_nonnull_ref_or_enomem(new (nothrow) Service(config, name)));
}

bool Service::is_enabled_for_system_mode(StringView mode) const
{
    return m_system_modes.contains_slow(mode);
}

ErrorOr<void> Service::determine_account(int fd)
{
    struct ucred creds = {};
    socklen_t creds_size = sizeof(creds);
    TRY(Core::System::getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &creds, &creds_size));

    m_account = TRY(Core::Account::from_uid(creds.uid, Core::Account::Read::PasswdOnly));
    return {};
}

Service::~Service()
{
    if (m_pid == -1)
        return; // Don't attempt to remove sockets if this service was never started.

    for (auto& socket : m_sockets) {
        if (auto rc = remove(socket.path.characters()); rc != 0)
            dbgln("{}", Error::from_errno(errno));
    }
}


Review comment (suggestion):
For a multi-instance services `m_pid == -1` but you will still want to remove the `notifier_socker`, right?
Sorry, I don't have time to look more into this right now.

Code after:
    VERIFY(!m_accept_socket_connections || (m_sockets.size() == 1 && m_lazy && m_multi_instance));
    // MultiInstance doesn't work with KeepAlive.
    VERIFY(!m_multi_instance || !m_keep_alive);
}

ErrorOr<NonnullRefPtr<Service>> Service::try_create(Core::ConfigFile const& config, StringView name)
{
    return TRY(adopt_nonnull_ref_or_enomem(new (nothrow) Service(config, name)));
}

bool Service::is_enabled_for_system_mode(StringView mode) const
{
    return m_system_modes.contains_slow(mode);
}

ErrorOr<void> Service::determine_account(int fd)
{
    struct ucred creds = {};
    socklen_t creds_size = sizeof(creds);
    TRY(Core::System::getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &creds, &creds_size));

    m_account = TRY(Core::Account::from_uid(creds.uid, Core::Account::Read::PasswdOnly));
    return {};
}

Service::~Service()
{
    for (auto& socket : m_sockets) {
        if (!socket.was_created)
            continue;

        auto result = Core::System::unlink(socket.path);
        if (result.is_error())
            dbgln("unlink(\"{}\") failed: {}", socket.path, result.error());
    }
}
Repository: SerenityOS/serenity
File: Toolchain/BuildCMake.sh (Shell)

Code before:
CMAKE_ARCHIVE_SHA256=313b6880c291bd4fe31c0aa51d6e62659282a521e695f30d5cc0d25abbd5c208
CMAKE_ARCHIVE=cmake-${CMAKE_VERSION}.tar.gz
CMAKE_ARCHIVE_URL=https://github.com/Kitware/CMake/releases/download/v${CMAKE_VERSION}/${CMAKE_ARCHIVE}

mkdir -p "$DIR"/Tarballs
pushd "$DIR"/Tarballs
    if [ ! -e "${CMAKE_ARCHIVE}" ]; then
        echo "Downloading CMake from ${CMAKE_ARCHIVE_URL}..."
        curl "${CMAKE_ARCHIVE_URL}" -L -o "${CMAKE_ARCHIVE}"
    else
        echo "${CMAKE_ARCHIVE} already exists, not downloading archive"
    fi

    if ! check_sha256 "${CMAKE_ARCHIVE}" "${CMAKE_ARCHIVE_SHA256}"; then
        echo "CMake archive SHA256 sum mismatch, please run script again"
        rm -f "${CMAKE_ARCHIVE}"
        exit 1
    fi

    if [ ! -d "cmake-${CMAKE_VERSION}" ]; then
        echo "Extracting ${CMAKE_ARCHIVE}..."
        tar -xf "${CMAKE_ARCHIVE}"
    else
        echo "cmake-${CMAKE_VERSION} already exists, not extracting archive"
    fi
popd

mkdir -p "${PREFIX_DIR}"

rm -rf "${BUILD_DIR}"
mkdir -p "${BUILD_DIR}"

pushd "${BUILD_DIR}"
    "${TARBALLS_DIR}"/cmake-"${CMAKE_VERSION}"/bootstrap --generator="Ninja" --prefix="${PREFIX_DIR}" --parallel="${MAKEJOBS}"
    ninja -j "${MAKEJOBS}"
    ninja install
popd


Review comment (suggestion):
Not that it is a blocker, but IIRC this will make `BuildCMake.sh` behave differently than all others `Build` scripts.

Code after:
CMAKE_ARCHIVE_SHA256=157e5be6055c154c34f580795fe5832f260246506d32954a971300ed7899f579
CMAKE_ARCHIVE=cmake-${CMAKE_VERSION}.tar.gz
CMAKE_ARCHIVE_URL=https://github.com/Kitware/CMake/releases/download/v${CMAKE_VERSION}/${CMAKE_ARCHIVE}

mkdir -p "$DIR"/Tarballs
pushd "$DIR"/Tarballs
    if [ ! -e "${CMAKE_ARCHIVE}" ]; then
        echo "Downloading CMake from ${CMAKE_ARCHIVE_URL}..."
        curl "${CMAKE_ARCHIVE_URL}" -L -o "${CMAKE_ARCHIVE}"
    else
        echo "${CMAKE_ARCHIVE} already exists, not downloading archive"
    fi

    if ! check_sha256 "${CMAKE_ARCHIVE}" "${CMAKE_ARCHIVE_SHA256}"; then
        echo "CMake archive SHA256 sum mismatch, please run script again"
        rm -f "${CMAKE_ARCHIVE}"
        exit 1
    fi

    if [ ! -d "cmake-${CMAKE_VERSION}" ]; then
        echo "Extracting ${CMAKE_ARCHIVE}..."
        tar -xf "${CMAKE_ARCHIVE}"
    else
        echo "cmake-${CMAKE_VERSION} already exists, not extracting archive"
    fi
popd

mkdir -p "${PREFIX_DIR}"

rm -rf "${BUILD_DIR}"
mkdir -p "${BUILD_DIR}"

pushd "${BUILD_DIR}"
    "${TARBALLS_DIR}"/cmake-"${CMAKE_VERSION}"/bootstrap --generator="Ninja" --prefix="${PREFIX_DIR}" --parallel="${MAKEJOBS}"
    ninja -j "${MAKEJOBS}"
    ninja install
popd
Repository: SerenityOS/serenity
File: AK/SIMDMath.h (C/C++)

Code before:
}

ALWAYS_INLINE static f32x4 exp(f32x4 v)
{
    // FIXME: This should be replaced with a vectorized algorithm instead of calling the scalar expf 4 times
    return f32x4 {
        expf(v[0]),
        expf(v[1]),
        expf(v[2]),
        expf(v[3]),
    };
}

ALWAYS_INLINE static f32x4 exp_approximate(f32x4 v)
{
    static constexpr int number_of_iterations = 10;
    auto result = 1.f + v / (1 << number_of_iterations);
    for (int i = 0; i < number_of_iterations; ++i)
        result *= result;
    return result;
}

ALWAYS_INLINE static f32x4 sqrt(f32x4 v)
{
#if ARCH(X86_64)
#    if defined(AK_COMPILER_CLANG)
    return __builtin_elementwise_sqrt(v);
#    else
    return __builtin_ia32_sqrtps(v);
#    endif
#else
    return f32x4 {
        AK::sqrt(v[0]),
        AK::sqrt(v[1]),
        AK::sqrt(v[2]),
        AK::sqrt(v[3]),
    };
#endif
}

}


Review comment (suggestion):
I think part of the motivation for `__builtin_elementwise_sqrt` is that it's target-independent, so we could lift it out of the `#if ARCH(X86_64)` probably.

Code after:
}

ALWAYS_INLINE static f32x4 exp(f32x4 v)
{
    // FIXME: This should be replaced with a vectorized algorithm instead of calling the scalar expf 4 times
    return f32x4 {
        expf(v[0]),
        expf(v[1]),
        expf(v[2]),
        expf(v[3]),
    };
}

ALWAYS_INLINE static f32x4 exp_approximate(f32x4 v)
{
    static constexpr int number_of_iterations = 10;
    auto result = 1.f + v / (1 << number_of_iterations);
    for (int i = 0; i < number_of_iterations; ++i)
        result *= result;
    return result;
}

ALWAYS_INLINE static f32x4 sqrt(f32x4 v)
{
#if __has_builtin(__builtin_elementwise_sqrt)
    return __builtin_elementwise_sqrt(v);
#elif __has_builtin(__builtin_ia32_sqrtps)
    return __builtin_ia32_sqrtps(v);
#else
    return f32x4 {
        AK::sqrt(v[0]),
        AK::sqrt(v[1]),
        AK::sqrt(v[2]),
        AK::sqrt(v[3]),
    };
#endif
}

}
Repository: SerenityOS/serenity
File: Ports/tree-sitter/package.sh (Shell)

Code before:
#!/usr/bin/env -S bash ../.port_include.sh
port='tree-sitter'
version='0.26.3'
workdir="${port}-${version}"
useconfigure='true'
files=(
    "https://github.com/tree-sitter/tree-sitter/archive/refs/tags/v${version}.tar.gz#7f4a7cf0a2cd217444063fe2a4d800bc9d21ed609badc2ac20c0841d67166550"
)

configure() {
    run cmake \
        -S . \
        -B 'build' \
        -DCMAKE_BUILD_TYPE='Release' \
        -DCMAKE_C_FLAGS="-D_GNU_SOURCE" \
        -DCMAKE_INSTALL_PREFIX="${SERENITY_INSTALL_ROOT}"
}

build() {
    run cmake --build build
}

install() {
    run cmake --install build
}


Review comment (suggestion):
Instead of doing this, pass `"-DCMAKE_TOOLCHAIN_FILE=${SERENITY_BUILD_DIR}/CMakeToolchain.txt"`, similar to the FAudio port I added recently: https://github.com/SerenityOS/serenity/blob/dd6ab8a5583824fdf2968c60fb152acd7fd0463e/Ports/FAudio/package.sh

Similarly, I would specify `configopts` like how I did it for FAudio and simply do `run cmake -G Ninja -B build -S . "${configopts[@]}"` here.

We also typically use ninja for everything in our builds if possible.

Code after:
#!/usr/bin/env -S bash ../.port_include.sh
port='tree-sitter'
version='0.26.3'
useconfigure='true'
files=(
    "https://github.com/tree-sitter/tree-sitter/archive/refs/tags/v${version}.tar.gz#7f4a7cf0a2cd217444063fe2a4d800bc9d21ed609badc2ac20c0841d67166550"
)

configopts=(
    '-DCMAKE_BUILD_TYPE=Release'
    "-DCMAKE_TOOLCHAIN_FILE=${SERENITY_BUILD_DIR}/CMakeToolchain.txt"
)

configure() {
    run cmake -G Ninja -B build -S . "${configopts[@]}"
}

build() {
    run cmake --build build --parallel "${MAKEJOBS}"
}

install() {
    run cmake --install build
}
Repository: Shaunwei/RealChar
File: client/web/src/components/Languages/index.jsx (JavaScript)

Code before:
/**
 * src/components/Languages/index.jsx
 * Select a language: English or Spanish
 * 
 * created by Lynchee on 7/20/23
 */

import React from 'react';
import './style.css'

const Languages = ({preferredLanguage, setPreferredLanguage}) => {
    const languages = ["English", "Spanish"];

    return (
        <div className="language-container">
            <label className="languages-label" htmlFor="languages-selection">Select preferred language:</label>
            <div id="languages-selection" className="select-dropdown">
                <select value={preferredLanguage} onChange={(e) => setPreferredLanguage(e.target.value)}>
                    <option disabled value="">Select Language</option>
                    {languages.map((language, index) => <option key={index} value={language}>{language}</option>)}
                </select>
            </div>
        </div>
    )
}

export default Languages;


Review comment (suggestion):
```suggestion
        <div className="languages-container">
```

Code after:
/**
 * src/components/Languages/index.jsx
 * Select a language: currently support English or Spanish
 * 
 * created by pycui on 7/28/23
 */

import React from 'react';
import './style.css'

const Languages = ({preferredLanguage, setPreferredLanguage}) => {
    const languages = ["English", "Spanish"];

    return (
        <div className="languages-container">
            <label className="languages-label" htmlFor="languages-selection">Select preferred language:</label>
            <div id="languages-selection" className="select-dropdown">
                <select value={preferredLanguage} onChange={(e) => setPreferredLanguage(e.target.value)}>
                    <option disabled value="">Select Language</option>
                    {languages.map((language, index) => <option key={index} value={language}>{language}</option>)}
                </select>
            </div>
        </div>
    )
}

export default Languages;
Repository: ShiqiYu/libfacedetection
File: opencv_dnn/cpp/detect-image.cpp (C++)

Code before:
#include <vector>
#include <string>
#include <iostream>

#include "priorbox.hpp"
#include "utils.hpp"

#include "opencv2/opencv.hpp"

int main(int argc, char* argv[]) {
    if (argc != 3 && argc !=4) {
        std::cout << "Usage: " << argv[0] << " <image_file_name> <net_file_name>\n";
        std::cout << "To turn the visual display on, add a fourth argument \"vis\"\n";
        return -1;
    }

    // Build blob
    cv::Mat img = cv::imread(argv[1], cv::IMREAD_COLOR);
    if (img.empty()) {
        std::cerr << "Cannot load the image file " << argv[1] << ".\n";
        return -1;
    }
    cv::Size img_shape = img.size();
    cv::Mat blob = cv::dnn::blobFromImage(img);

    // Load .onnx model using OpenCV's DNN module
    cv::dnn::Net net = cv::dnn::readNet(argv[2]);
    net.setPreferableBackend(cv::dnn::DNN_BACKEND_DEFAULT);
    net.setPreferableTarget(cv::dnn::DNN_TARGET_CPU);

    // Inference hyperparameters
    float conf_thresh = 0.6;
    float nms_thresh = 0.3;
    int keep_top_k = 750;
    // Result
    bool vis = false;
    std::string save_fpath = "./result.jpg";


Review comment (suggestion):
Make it simple:
```cpp
std::cout << "Usage: " << argv[0] << " <image_file_name> <net_file_name> [<visualization_flag> default false] \n";
```

Code after:
#include <vector>
#include <string>
#include <iostream>

#include "priorbox.hpp"
#include "utils.hpp"

#include "opencv2/opencv.hpp"

int main(int argc, char* argv[]) {
    if (argc != 3 && argc !=4) {
        std::cout << "Usage: " << argv[0] << " <image_file_name> <net_file_name> [<visualization_flag> default false] \n";
        return -1;
    }

    // Build blob
    cv::Mat img = cv::imread(argv[1], cv::IMREAD_COLOR);
    if (img.empty()) {
        std::cerr << "Cannot load the image file " << argv[1] << ".\n";
        return -1;
    }
    cv::Size img_shape = img.size();
    cv::Mat blob = cv::dnn::blobFromImage(img);

    // Load .onnx model using OpenCV's DNN module
    cv::dnn::Net net = cv::dnn::readNet(argv[2]);
    net.setPreferableBackend(cv::dnn::DNN_BACKEND_DEFAULT);
    net.setPreferableTarget(cv::dnn::DNN_TARGET_CPU);

    // Inference hyperparameters
    float conf_thresh = 0.6;
    float nms_thresh = 0.3;
    int keep_top_k = 750;
    // Result
    bool vis = false;
    if (argc==4 && std::string(argv[3]) == "true") {
        vis = true;
    }
Repository: ShiqiYu/libfacedetection
File: opencv_dnn/cpp/detect-image.cpp (C++)

Code before:
            face_boxes.push_back(d.bbox_tlwh);
            face_scores.push_back(d.score);
        }
        std::vector<int> keep_idx;
        cv::dnn::NMSBoxes(face_boxes, face_scores, conf_thresh, nms_thresh, keep_idx, 1.f, keep_top_k);
        for (size_t i = 0; i < keep_idx.size(); i++) {
            size_t idx = keep_idx[i];
            nms_dets.push_back(dets[idx]);
        }
    }
    else if (dets.size() < 1) {
        std::cout << "No faces found." << std::endl;
        return 1;
    }
    std::cout << "Detection results: " << nms_dets.size() << " faces found." << std::endl;
    for (auto i = 0; i < nms_dets.size(); ++i) {
        Box bbox = nms_dets[i].bbox_tlwh;
        float score = nms_dets[i].score;
        std::cout << "[" << bbox.x << ", " << bbox.y << "] [" << bbox.x + bbox.width << ", " << bbox.y + bbox.height << "] " << score << std::endl;
    }

    // Draw and display
    draw(img, nms_dets);
    if (argc==4 && std::string(argv[3]) == "vis") {
        vis = true;
    }
    if (vis) {
        cv::String title = cv::String("Detection Results on") + cv::String(argv[1]);
        cv::imshow(title, img);
        cv::waitKey(0);
        cv::destroyAllWindows();
    }
    cv::imwrite(save_fpath, img);

    return 0;
}

Review comment (suggestion):
Place this block under `bool vis = false`.
Condition: `argc==4 && std::string(argv[3]) == "vis"` -> `argc==4 && std::string(argv[3]) == "true"`.

Code after:
        std::vector<float> face_scores;
        for (auto d: dets) {
            face_boxes.push_back(d.bbox_tlwh);
            face_scores.push_back(d.score);
        }
        std::vector<int> keep_idx;
        cv::dnn::NMSBoxes(face_boxes, face_scores, conf_thresh, nms_thresh, keep_idx, 1.f, keep_top_k);
        for (size_t i = 0; i < keep_idx.size(); i++) {
            size_t idx = keep_idx[i];
            nms_dets.push_back(dets[idx]);
        }
    }
    else if (dets.size() < 1) {
        std::cout << "No faces found." << std::endl;
        return 1;
    }
    std::cout << "Detection results: " << nms_dets.size() << " faces found." << std::endl;
    for (auto i = 0; i < nms_dets.size(); ++i) {
        Box bbox = nms_dets[i].bbox_tlwh;
        float score = nms_dets[i].score;
        std::cout << "[" << bbox.x << ", " << bbox.y << "] [" << bbox.x + bbox.width << ", " << bbox.y + bbox.height << "] " << score << std::endl;
    }

    // Draw and display
    draw(img, nms_dets);
    if (vis) {
        cv::String title = cv::String("Detection Results on") + cv::String(argv[1]);
        cv::imshow(title, img);
        cv::waitKey(0);
        cv::destroyAllWindows();
    }
    cv::imwrite(save_fpath, img);

    return 0;
}
Repository: Shpota/goxygen
File: codegen/codegen.go (Go)

Code before:
	fmt.Println("Generating", projectName)
	processTextFiles(projectName, framework)
	processImages(projectName, framework)
	err := initGitRepo(projectName)
	if err != nil {
		fmt.Println("Failed to setup a Git repository:", err)
	}
	fmt.Println("Generation completed.")
}

func processImages(projectName string, framework string) {
	for path, binary := range static.Images() {
		if !include(path, framework) {
			continue
		}
		path = strings.Replace(path, framework+".", "", 1)
		generateFile(projectName, path, binary)
	}
}

func processTextFiles(projectName string, framework string) {
	for path, srcText := range static.Sources() {
		if !include(path, framework) {
			continue
		}
		path = strings.Replace(path, framework+".", "", 1)
		srcText = strings.ReplaceAll(srcText, "project-name", projectName)
		binary := []byte(srcText)
		generateFile(projectName, path, binary)
	}
}

func generateFile(pjRoot string, path string, content []byte) {
	pathElements := strings.Split(path, "/")
	separator := string(os.PathSeparator)
	pathElements = append([]string{pjRoot}, pathElements...)
	_ = os.MkdirAll(
		strings.Join(pathElements[:len(pathElements)-1], separator),
		os.ModePerm,
	)
	fmt.Println("creating: " + strings.Join(pathElements, separator))
	err := ioutil.WriteFile(
		strings.Join(pathElements, separator),
		content,
		0644,
	)
	if err != nil {
		log.Fatal(err)
	}
}


Review comment (refactor):
I would suggest to move this line to the `generateFile` Method as it is needed for images as well as text files, this would reduce duplication.

Code after:
	projectName string
	frontend    string
}

func Generate(projectName, frontend string) {
	g := generator{projectName, frontend}
	g.generate()
}

func (g generator) generate() {
	fmt.Println("Generating", g.projectName)
	for path, srcText := range static.Sources() {
		srcText = strings.ReplaceAll(srcText, "project-name", g.projectName)
		binary := []byte(srcText)
		g.processFile(path, binary)
	}
	for path, binary := range static.Images() {
		g.processFile(path, binary)
	}
	err := g.initGitRepo()
	if err != nil {
		fmt.Println("Failed to setup a Git repository:", err)
	}
	fmt.Println("Generation completed.")
}

// Checks if a file with the given path has to be generated, creates
// a directory structure, and a file with the given content.
func (g generator) processFile(path string, content []byte) {
	if !g.needed(path) {
		return
	}
	path = strings.Replace(path, g.frontend+".", "", 1)
	pathElements := strings.Split(path, "/")
	separator := string(os.PathSeparator)
	pathElements = append([]string{g.projectName}, pathElements...)
	_ = os.MkdirAll(
		strings.Join(pathElements[:len(pathElements)-1], separator),
		os.ModePerm,
	)
	fmt.Println("creating: " + strings.Join(pathElements, separator))
	err := ioutil.WriteFile(
		strings.Join(pathElements, separator),
		content,
		0644,
	)
	if err != nil {
		log.Fatal(err)
	}
}
Repository: Shpota/goxygen
File: templates/server/web/app_test.go (Go)

Code before:
package web

import (
	"errors"
	"net/http"
	"net/http/httptest"
	"project-name/model"
	"testing"
)

var expectedTechnologies = []*model.Technology{
	{
		Name:    "Tech1",
		Details: "Details1",
	},
	{
		Name:    "Tech2",
		Details: "Details2",
	},
}

type MockDb struct {
	called     int
	returnTech []*model.Technology
	returnErr  error
}

func (m *MockDb) GetTechnologies() ([]*model.Technology, error) {
	m.called++
	return m.returnTech, m.returnErr
}

func TestApp_GetTechnologies(t *testing.T) {
	mockDb := &MockDb{
		returnTech: expectedTechnologies,
	}
	app := App{d: mockDb}

	req := buildTechnologiesRequest(t)
	recorder := httptest.NewRecorder()


Review comment (suggestion):
I guess, an one-entry-slice is enough for testing.

I would also suggest embedding this data directly to the test function.

```go
app := App{d: &MockDb{
	tech: []*model.Technology{
		{"Tech1", "Details1"},
		{"Tech2", "Details2"},
	},
}}
```
This way we don't reuse the slice, but we gain more in readability as it is clear what exactly is mocked and the user can see the whole body of the test in one place.

Code after:
package web

import (
	"errors"
	"net/http"
	"net/http/httptest"
	"project-name/model"
	"testing"
)

type MockDb struct {
	tech []*model.Technology
	err  error
}

func (m *MockDb) GetTechnologies() ([]*model.Technology, error) {
	return m.tech, m.err
}

func TestApp_GetTechnologies(t *testing.T) {
	app := App{d: &MockDb{
		tech: []*model.Technology{
			{"Tech1", "Details1"},
			{"Tech2", "Details2"},
		},
	}}

	r, _ := http.NewRequest("GET", "/api/technologies", nil)
	w := httptest.NewRecorder()

	app.GetTechnologies(w, r)

	if w.Code != http.StatusOK {
		t.Errorf("handler returned wrong status code: got %v want %v", w.Code, http.StatusOK)
	}

	want := `[{"name":"Tech1","details":"Details1"},{"name":"Tech2","details":"Details2"}]` + "\n"
	if got := w.Body.String(); got != want {
		t.Errorf("handler returned unexpected body: got %v want %v", got, want)
	}
}
Repository: Shpota/goxygen
File: templates/server/web/app_test.go (Go)

Code before:
	}
}

func TestApp_GetTechnologies_WithDBError(t *testing.T) {
	mockDb := &MockDb{
		returnTech: nil,
		returnErr:  errors.New("unknown error"),
	}
	app := App{d: mockDb}

	req := buildTechnologiesRequest(t)
	recorder := httptest.NewRecorder()

	app.GetTechnologies(recorder, req)

	verifyDbWasCalledOnce(t, mockDb)
	status := recorder.Code
	if status != http.StatusInternalServerError {
		t.Errorf("handler returned wrong status code: got %v want %v", status, http.StatusOK)
	}

}

func buildTechnologiesRequest(t *testing.T) *http.Request {
	req, err := http.NewRequest("GET", "/api/technologies", nil)
	if err != nil {
		t.Fatal(err)
	}
	return req
}

func verifyDbWasCalledOnce(t *testing.T, db *MockDb) {
	if db.called != 1 {
		t.Errorf("db was called %d times instead of once", db.called)
	}
}


Review comment (bug):
There is no need to handle this error. It could only happen when an input method is wrong or a URL is unparsable, but both the parameters are controlled by the developer. It would only be needed if these parameters came from outside. 

I'd suggest to use
```go
r, _ := http.NewRequest("GET", "/api/technologies", nil)
```
directly in the test body.

Code after:
package web

import (
	"errors"
	"net/http"
	"net/http/httptest"
	"project-name/model"
	"testing"
)

type MockDb struct {
	tech []*model.Technology
	err  error
}

func (m *MockDb) GetTechnologies() ([]*model.Technology, error) {
	return m.tech, m.err
}

func TestApp_GetTechnologies(t *testing.T) {
	app := App{d: &MockDb{
		tech: []*model.Technology{
			{"Tech1", "Details1"},
			{"Tech2", "Details2"},
		},
	}}

	r, _ := http.NewRequest("GET", "/api/technologies", nil)
	w := httptest.NewRecorder()

	app.GetTechnologies(w, r)

	if w.Code != http.StatusOK {
		t.Errorf("handler returned wrong status code: got %v want %v", w.Code, http.StatusOK)
	}

	want := `[{"name":"Tech1","details":"Details1"},{"name":"Tech2","details":"Details2"}]` + "\n"
	if got := w.Body.String(); got != want {
		t.Errorf("handler returned unexpected body: got %v want %v", got, want)
	}
}

func TestApp_GetTechnologies_WithDBError(t *testing.T) {
	app := App{d: &MockDb{
		tech: nil,
		err:  errors.New("unknown error"),
	}}

	r, _ := http.NewRequest("GET", "/api/technologies", nil)
	w := httptest.NewRecorder()

	app.GetTechnologies(w, r)

	if w.Code != http.StatusInternalServerError {
		t.Errorf("handler returned wrong status code: got %v want %v", w.Code, http.StatusOK)
	}

}