Skip to content

Commit

Permalink
formatter test
Browse files Browse the repository at this point in the history
  • Loading branch information
hiuns committed Dec 20, 2024
1 parent 7e97946 commit 21cfbe6
Show file tree
Hide file tree
Showing 6 changed files with 237 additions and 0 deletions.
30 changes: 30 additions & 0 deletions .github/workflows/check.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
name: Format Check

on:
push:
branches:
- main
pull_request:
branches:
- main

jobs:
check-format:
name: Check Go Format
runs-on: ubuntu-latest

steps:
- name: Checkout Code
uses: actions/checkout@v3

- name: Set up Go
uses: actions/setup-go@v4
with:
go-version: 1.21 # Update with your Go version

- name: Install Make (if needed)
run: sudo apt-get install -y make

- name: Run Format Check using Makefile
run: make check

13 changes: 13 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# Check if all Go files are formatted
check:
@OUTPUT=$$(gofmt -l .); \
if [ -n "$$OUTPUT" ]; then \
echo "The following files are not formatted. Run 'make format' to fix them:"; \
echo "$$OUTPUT"; \
exit 1; \
fi

# Format all Go files
format:
gofmt -w .

74 changes: 74 additions & 0 deletions concurrency/example/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
package main

import (
"errors"
"fmt"
"sync"
)

// Task is a function that returns an error
type Task func() error

// WorkerPool processes tasks concurrently using a fixed number of workers.
func WorkerPool(tasks []Task, workerCount int) []error {
var wg sync.WaitGroup
taskCh := make(chan Task)
errCh := make(chan error, len(tasks)) // Buffered to hold all potential errors

// Start workers
for i := 0; i < workerCount; i++ {
wg.Add(1)
go func() {
defer wg.Done()
for task := range taskCh {
if err := task(); err != nil {
errCh <- err
}
}
}()
}

// Send tasks to the taskCh
go func() {
for _, task := range tasks {
taskCh <- task
}
close(taskCh)
}()

// Wait for all workers to finish
wg.Wait()
close(errCh)

// Collect errors
var errors []error
for err := range errCh {
errors = append(errors, err)
}

return errors
}

func main() {
// Example tasks
tasks := []Task{
func() error { return nil },
func() error { return errors.New("Task 2 failed") },
func() error { return nil },
func() error { return errors.New("Task 4 failed") },
}

// Run WorkerPool
workerCount := 3
errors := WorkerPool(tasks, workerCount)

// Print results
if len(errors) == 0 {
fmt.Println("All tasks completed successfully")
} else {
fmt.Println("Errors:")
for _, err := range errors {
fmt.Println(err)
}
}
}
105 changes: 105 additions & 0 deletions concurrency/example/main_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
package main

import (
"errors"
"fmt"
"sync"
"testing"
"time"
)

func TestNoChannelExample(t *testing.T) {
go func() {
fmt.Println("Running without channels")
time.Sleep(1 * time.Second)
}()
time.Sleep(2 * time.Second)
fmt.Println("No-channel example done")
}

func TestChannelExample(t *testing.T) {
ch := make(chan string)
go func() { ch <- "Running with goroutine" }()
fmt.Println(<-ch)
fmt.Println("Channel example done")
}

func TestWorkerPool_Success(t *testing.T) {
tasks := []Task{
func() error { return nil },
func() error { return nil },
func() error { return nil },
}

workerCount := 2
errors := WorkerPool(tasks, workerCount)

if len(errors) != 0 {
t.Fatalf("expected no errors, got %d errors: %v", len(errors), errors)
}
}

func TestWorkerPool_Errors(t *testing.T) {
// Create tasks with some failures
tasks := []Task{
func() error { return errors.New("Task 1 failed") },
func() error { return nil },
func() error { return errors.New("Task 3 failed") },
}

workerCount := 3
errors := WorkerPool(tasks, workerCount)

// Verify the correct number of errors
if len(errors) != 2 {
t.Fatalf("expected 2 errors, got %d: %v", len(errors), errors)
}
}

func TestWorkerPool_Concurrency(t *testing.T) {
var mu sync.Mutex
taskOrder := []int{}

// Create tasks that add their index to the taskOrder slice
tasks := []Task{
func() error {
mu.Lock()
taskOrder = append(taskOrder, 1)
mu.Unlock()
return nil
},
func() error {
mu.Lock()
taskOrder = append(taskOrder, 2)
mu.Unlock()
return nil
},
func() error {
mu.Lock()
taskOrder = append(taskOrder, 3)
mu.Unlock()
return nil
},
}

workerCount := 2
_ = WorkerPool(tasks, workerCount)

// Verify that all tasks were executed
if len(taskOrder) != len(tasks) {
t.Fatalf("expected %d tasks to be executed, but got %d", len(tasks), len(taskOrder))
}
}

func TestWorkerPool_NoTasks(t *testing.T) {
// Empty task list
tasks := []Task{}

workerCount := 3
errors := WorkerPool(tasks, workerCount)

// No errors should occur since no tasks exist
if len(errors) != 0 {
t.Fatalf("expected no errors, got %d: %v", len(errors), errors)
}
}
9 changes: 9 additions & 0 deletions concurrency/go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
module concurrency

go 1.23.3

require (
golang.org/x/mod v0.22.0 // indirect
golang.org/x/sync v0.10.0 // indirect
golang.org/x/tools v0.28.0 // indirect
)
6 changes: 6 additions & 0 deletions concurrency/go.sum
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
golang.org/x/mod v0.22.0 h1:D4nJWe9zXqHOmWqj4VMOJhvzj7bEZg4wEYa759z1pH4=
golang.org/x/mod v0.22.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY=
golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ=
golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/tools v0.28.0 h1:WuB6qZ4RPCQo5aP3WdKZS7i595EdWqWR8vqJTlwTVK8=
golang.org/x/tools v0.28.0/go.mod h1:dcIOrVd3mfQKTgrDVQHqCPMWy6lnhfhtX3hLXYVLfRw=

0 comments on commit 21cfbe6

Please sign in to comment.