<commit_before>package rmq

import (
	"errors"
	"strings"
	"sync"
	"time"
)

// TestRedisClient is a mock for redis
type TestRedisClient struct {
	store sync.Map
	ttl   sync.Map
	mx    sync.Mutex
}

// NewTestRedisClient returns a NewTestRedisClient

func NewTestRedisClient() *TestRedisClient {
	return &TestRedisClient{}
}

// Set sets key to hold the string value.
// If key already holds a value, it is overwritten, regardless of its type.
// Any previous time to live associated with the key is discarded on successful SET operation.
func (client *TestRedisClient) Set(key string, value string, expiration time.Duration) error {

	client.mx.Lock()
	defer client.mx.Unlock()

	client.store.Store(key, value)
	// Delete any previous time to live associated with the key
	client.ttl.Delete(key)

	// 0.0 expiration means that the value won't expire
	if expiration.Seconds() != 0.0 {
		// Store the unix time at which we should delete this
		client.ttl.Store(key, time.Now().Add(expiration).Unix())
	}

	return nil
}

// Get the value of key.
// If the key does not exist or isn't a string
// the special value nil is returned.
func (client *TestRedisClient) Get(key string) (string, error) {

	value, found := client.store.Load(key)

	if found {
		if stringValue, casted := value.(string); casted {
			return stringValue, nil
		}
	}

	return "nil", nil
}

// Del removes the specified key. A key is ignored if it does not exist.
func (client *TestRedisClient) Del(key string) (affected int64, err error) {

	_, found := client.store.Load(key)
	client.store.Delete(key)
	client.ttl.Delete(key)

	if found {
		return 1, nil
	}
	return 0, nil

}

// TTL returns the remaining time to live of a key that has a timeout.
// This introspection capability allows a Redis client to check how many seconds a given key will continue to be part of the dataset.
// In Redis 2.6 or older the command returns -1 if the key does not exist or if the key exist but has no associated expire.
// Starting with Redis 2.8 the return value in case of error changed:
// The command returns -2 if the key does not exist.
// The command returns -1 if the key exists but has no associated expire.
func (client *TestRedisClient) TTL(key string) (ttl time.Duration, err error) {

	// Lookup the expiration map
	expiration, found := client.ttl.Load(key)

	// Found an expiration time
	if found {

		// It was there, but it expired; removing it now
		if expiration.(int64) < time.Now().Unix() {
			client.ttl.Delete(key)
			return -2, nil
		}

		ttl = time.Duration(expiration.(int64) - time.Now().Unix())
		return ttl, nil
	}

	// Lookup the store in case this key exists but don't have an expiration
	// date
	_, found = client.store.Load(key)

	// The key was in store but didn't have an expiration associated
	// to it.
	if found {
		return -1, nil
	}

	return -2, nil
}

// LPush inserts the specified value at the head of the list stored at key.
// If key does not exist, it is created as empty list before performing the push operations.
// When key holds a value that is not a list, an error is returned.
// It is possible to push multiple elements using a single command call just specifying multiple arguments
// at the end of the command. Elements are inserted one after the other to the head of the list,
// from the leftmost element to the rightmost element.
func (client *TestRedisClient) LPush(key string, values ...string) (total int64, err error) {

	client.mx.Lock()
	defer client.mx.Unlock()

	list, err := client.findList(key)

	if err != nil {
		return 0, nil
	}

	newList := append(values, list...)
	client.storeList(key, newList)
	return int64(len(newList)), nil
}

// RPop removes and returns one value from the tail of the list stored at key.
// When key holds a value that is not a list, an error is returned.
func (client *TestRedisClient) RPop(key string) (value string, err error) {

	client.mx.Lock()
	defer client.mx.Unlock()

	list, err := client.findList(key)
	// not a list
	if err != nil {
		return "", ErrorNotFound
	}
	// list is empty
	if len(list) == 0 {
		return "", ErrorNotFound
	}

	// Remove the last element of source (tail)
	client.storeList(key, list[0:len(list)-1])

	return list[len(list)-1], nil
}

// LLen returns the length of the list stored at key.
// If key does not exist, it is interpreted as an empty list and 0 is returned.
// An error is returned when the value stored at key is not a list.
func (client *TestRedisClient) LLen(key string) (affected int64, err error) {
	list, err := client.findList(key)<commit_msg>use redis nil in rpop<commit_after>package rmq

import (
	"errors"
	"strings"
	"sync"
	"time"

	"github.com/go-redis/redis/v8"
)

// TestRedisClient is a mock for redis
type TestRedisClient struct {
	store sync.Map
	ttl   sync.Map
	mx    sync.Mutex
}

// NewTestRedisClient returns a NewTestRedisClient

func NewTestRedisClient() *TestRedisClient {
	return &TestRedisClient{}
}

// Set sets key to hold the string value.
// If key already holds a value, it is overwritten, regardless of its type.
// Any previous time to live associated with the key is discarded on successful SET operation.
func (client *TestRedisClient) Set(key string, value string, expiration time.Duration) error {

	client.mx.Lock()
	defer client.mx.Unlock()

	client.store.Store(key, value)
	// Delete any previous time to live associated with the key
	client.ttl.Delete(key)

	// 0.0 expiration means that the value won't expire
	if expiration.Seconds() != 0.0 {
		// Store the unix time at which we should delete this
		client.ttl.Store(key, time.Now().Add(expiration).Unix())
	}

	return nil
}

// Get the value of key.
// If the key does not exist or isn't a string
// the special value nil is returned.
func (client *TestRedisClient) Get(key string) (string, error) {

	value, found := client.store.Load(key)

	if found {
		if stringValue, casted := value.(string); casted {
			return stringValue, nil
		}
	}

	return "nil", nil
}

// Del removes the specified key. A key is ignored if it does not exist.
func (client *TestRedisClient) Del(key string) (affected int64, err error) {

	_, found := client.store.Load(key)
	client.store.Delete(key)
	client.ttl.Delete(key)

	if found {
		return 1, nil
	}
	return 0, nil

}

// TTL returns the remaining time to live of a key that has a timeout.
// This introspection capability allows a Redis client to check how many seconds a given key will continue to be part of the dataset.
// In Redis 2.6 or older the command returns -1 if the key does not exist or if the key exist but has no associated expire.
// Starting with Redis 2.8 the return value in case of error changed:
// The command returns -2 if the key does not exist.
// The command returns -1 if the key exists but has no associated expire.
func (client *TestRedisClient) TTL(key string) (ttl time.Duration, err error) {

	// Lookup the expiration map
	expiration, found := client.ttl.Load(key)

	// Found an expiration time
	if found {

		// It was there, but it expired; removing it now
		if expiration.(int64) < time.Now().Unix() {
			client.ttl.Delete(key)
			return -2, nil
		}

		ttl = time.Duration(expiration.(int64) - time.Now().Unix())
		return ttl, nil
	}

	// Lookup the store in case this key exists but don't have an expiration
	// date
	_, found = client.store.Load(key)

	// The key was in store but didn't have an expiration associated
	// to it.
	if found {
		return -1, nil
	}

	return -2, nil
}

// LPush inserts the specified value at the head of the list stored at key.
// If key does not exist, it is created as empty list before performing the push operations.
// When key holds a value that is not a list, an error is returned.
// It is possible to push multiple elements using a single command call just specifying multiple arguments
// at the end of the command. Elements are inserted one after the other to the head of the list,
// from the leftmost element to the rightmost element.
func (client *TestRedisClient) LPush(key string, values ...string) (total int64, err error) {

	client.mx.Lock()
	defer client.mx.Unlock()

	list, err := client.findList(key)

	if err != nil {
		return 0, nil
	}

	newList := append(values, list...)
	client.storeList(key, newList)
	return int64(len(newList)), nil
}

// RPop removes and returns one value from the tail of the list stored at key.
// When key holds a value that is not a list, an error is returned.
func (client *TestRedisClient) RPop(key string) (value string, err error) {

	client.mx.Lock()
	defer client.mx.Unlock()

	list, err := client.findList(key)
	// not a list
	if err != nil {
		return "", err
	}
	// list is empty
	if len(list) == 0 {
		return "", redis.Nil
	}

	// Remove the last element of source (tail)
	client.storeList(key, list[0:len(list)-1])

	return list[len(list)-1], nil
}

// LLen returns the length of the list stored at key.
// If key does not exist, it is interpreted as an empty list and 0 is returned.
// An error is returned when the value stored at key is not a list.
func (client *TestRedisClient) LLen(key string) (affected int64, err error) {
	list, err := client.findList(key)
{'fraction_non_alphanumeric': 0.09847571005592719, 'fraction_numerical': 0.007566619146836276, 'mean_word_length': 3.4100580270793035, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3266354', 'n_tokens_mistral': 2965, 'n_tokens_neox': 2794, 'n_words': 1238}